25. k个一组翻转链表

Posted shayue111

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了25. k个一组翻转链表相关的知识,希望对你有一定的参考价值。

题目描述

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

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

示例 :

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

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

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

说明:

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

算法

边界条件

  1. k值与链表长度。虽然题目说k 是一个正整数,它的值小于或等于链表的长度。但是实际提交的时候我发现。。。没错,k值大于链表长度也被作为一个测试点。
    k值大于链表长度

  2. 链表为空或者k值为1

思路

  1. 找到两个距离为k的节点
  2. 反转两个节点之间的这段链表
  3. 重复1、2步直到遍历完整个链表

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* global_head;
    ListNode* reverseKGroup(ListNode* head, int k) {
    
        // 边界条件
        if(head == NULL || k == 1)
            return head;
        int size = 0;
        for(ListNode* t = head; t; t = t->next, size++);
        if(size < k)
            return head;
        
        /*** H靠近链表头部,tail靠近链表尾部;
        pre_node定义为前一段已经反转的局部链表的最后一个节点;
        比如链表1->2->3->4->5->6,k=2;第一段局部链表反转为2->1,那么pre_node指向1这个节点;
        pre_node初值设为NULL,可以在reverse_k中判断是不是第一段局部链表的反转,如果是第一段的话,需要设置反转后的链表头部节点global_head
        ***/
        ListNode *H, *tail, *pre_node = NULL;
        H = tail = head;
        
        // 遍历整个链表
        while(true)
        {
            // cnt用来记录H和tail节点之间的距离,
            int cnt = 0;
            while(cnt < k && tail != NULL)
            {
                tail = tail->next;
                cnt++;
            }
            
            // 1->2->3,k=3
            if(tail == NULL && cnt == k)
            {
                reverse_k(pre_node, H, tail);
                break;
            }
            // 最后剩余节点不足k个
            else if(cnt != k)
            {
                pre_node->next = H;
                break;
            }
            // 对k个节点反转
            else
            {
                reverse_k(pre_node, H, tail);
                H = tail;
            }
        }
        return global_head;
    }

    void reverse_k(ListNode *&pre_node, ListNode *&start, ListNode *&end) {

        /*** 这个函数将[start, end)之间的节点顺序逆置 ***/

        ListNode *pre, *p, *post;
        pre = start;
        p = pre->next;
        // 反转代码
        while(p != end)
        {
            post = p->next;
            p->next = pre;
            pre = p;
            p = post;
        }
        // 判断是不是第一段局部链表的反转以设置改动后的链表头节点global_head
        if(pre_node == NULL)
            global_head = pre;
        else
            // pre_node是前一段链表的最后一个节点,接上这段链表
            pre_node->next = pre;
        
        // 重新设置pre_node为这段链表的最后一个结点
        pre_node = start;
        pre_node->next = NULL;
    }
};

以上是关于25. k个一组翻转链表的主要内容,如果未能解决你的问题,请参考以下文章

链表--K个一组反转链表(leetcode 25

25. K 个一组翻转链表

leetCode 25 K个一组翻转链表

25. K 个一组翻转链表

25. k个一组翻转链表-LeetCode

25. K 个一组翻转链表