#每日一题# 25. K 个一组翻转链表 - 20191021

题目链接

K个一组翻转链表

题目大意

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

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例 :

给定这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明 :

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

解题思路

这里的思路是把整个链表分成 K 个结点一组的小链表,然后依次翻转每个小链表,再将这些小链表连起来就是答案。

为了实现这个目标,首先需要一个翻转链表的函数 reverse(),函数返回翻转后的链表,这个是比较简单的。

接下来,我们要把原始链表分成 K 个结点一组的小链表去翻转。

这里用 cnt 计数,ans 为最终翻转后的链表的头指针,p 为最终翻转后的链表的尾指针,temp 指向当前小链表的头结点,head 指向当前结点。

当 cnt+1 == K 时,说明从 temp 至 head 总共有 K 个结点,这个时候应该把这个小链表拿出来翻转一下然后接到 p 的后面。用 end 指向当前 head 指向的结点。令 end = NULL,就把小链表从原始链表上拿下来了。p->next = reverse(temp) 就把翻转后的小链表接到了当前已经翻转的链表的后面。再用一个 while 循环,把 p 更新为当前已经翻转的链表的尾指针。接下来开始找下一个小链表,首先更新 head = head->next,因为 temp 存储的是下一个小链表的头结点,所以要令 temp = head,这样又回到了初始状态,所以要 continue 跳过本次循环后面的内容;当 cnt + 1 ≠ K 时,head = head->next 即可。

最后还应有 p->next = temp,因为当最后一组结点没有 K 个时,是不会翻转的,但 temp 仍指向最后一组结点的头结点,直接把 temp 接到 p 后面即可。

参考代码如下:

class Solution {
public:
    ListNode* reverse(ListNode* head) {
        ListNode* ans = NULL;
        while(head) {
            ListNode* next = head->next;
            head->next = ans;
            ans = head;
            head = next;
        }
        return ans;
    }
    ListNode* reverseKGroup(ListNode* head, int k) {
        int cnt = 0;
        ListNode* ans = new ListNode(0);
        ListNode* temp = head, *p = ans;
        while(head) {
            cnt++;
            if(cnt == k) {
                cnt = 0;
                ListNode* end = head;
                head = head->next;
                end->next = NULL;
                p->next = reverse(temp);
                while(p->next) 
                    p = p->next;
                temp = head;
                continue;
            }
            head = head->next;
        }
        p->next = temp;
        return ans->next;
    }
};

解题感悟

这题周末想了好久都没搞出来,今天状态好,一会儿就做出来了,看来状态好的时候效率真的会很高呀,以后要尽量在状态好的时候做一些有难度的事情。

加油。

你可能感兴趣的:(链表)