力扣每日一题25:K个一组翻转链表

题目描述:

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:

力扣每日一题25:K个一组翻转链表_第1张图片

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例 2:

力扣每日一题25:K个一组翻转链表_第2张图片

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

提示:

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

进阶:你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?

通过次数

507.7K

提交次数

749.8K

通过率

67.7%

题目分析:

前面的第24题是两两交换节点,也就是两个一组翻转链表,就是本题k=2的情况。在两两交换的时候,我们用了一个cur指针始终指向每两个节点的前一个节点,这样在每次遍历时就只需要把cur->next指向的节点和cur->next->next指向的节点的next交换一下即可。但是这次的k可能是3,4,5甚至是100以上的数,如果还用交换的话会非常麻烦。

这里我们用每K个头插的方法。如果说给你一个链表,让你翻转的话非常简单,至于要遍历每个节点并且将每个节点依次插入链表的头部即可,这样得到的新链表就是一个翻转链表。这题k个一组翻转链表就相当于把多个节点数位K的链表翻转。所以我们只需要记录有多少个这样的链表并且将每一个翻转即可。

我们设置一个变量i记录遍历到节点的个数,并且设置一个指针数组ptr[]来记录k个节点的地址,指针p指向遍历的当前节点,指针cur指向每k个节点的前一个节点。初始值i=0,cur=新创建的头结点。当没有遍历到链表尾部时:ptr[i]=p,p=p->next,i++;当i=k时:依次将ptr[0]到ptr[k-1]所指向的节点连接到cur的后面,随后cur=ptr[0],i=0。最后p指向空时循环结束。

代码:

//头插法转置
struct ListNode* reverseKGroup(struct ListNode* head, int k){
    struct ListNode Head;
    Head.next=NULL;
    struct ListNode *cur,*p;
    cur=&Head;
    p=head;
    int i=0,j;
    struct ListNode *ptr[5000];
    while(1)
    {
        i=0;
        // ptr[0]=NULL;//加上这一句就不用单独判断i==0的情况,但是运行时间会更久
        //遍历是否还有k个节点
        while(p&&inext;
            i++;
        }
        if(i==k)
        {//如果还有k个节点,将这k个节点翻转后,遍历后面的节点
            for(j=0;jnext=cur->next;
                cur->next=ptr[j];
            }
            cur=ptr[0];
        }
        else if(i==0)
        {
            cur->next=NULL;
            break;
        }
        else
        {
            cur->next=ptr[0];
            break;
        }
    }
    return Head.next;
}

你可能感兴趣的:(LeetCode每日一题,leetcode,链表,算法)