25. K 个一组翻转链表

25. K 个一组翻转链表

题目描述

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

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

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

进阶:

你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

提示:

  • 列表中节点的数量在范围 sz
  • 1 <= sz <= 5000
  • 0 <= Node.val <= 1000
  • 1 <= k <= sz

思路分析

链表的问题其实很套路,最好在纸上或者脑海里想一想,要理清思路。对于本体,K个一组反转链表,那么就把链表分为K组,对于每个组,设定两个指针,一个指针head指向本组的开头,一个指针end指向本组的末尾,然后对本组进行翻转即可。对于每个组反转之后,还要把每个组连起来,那么再设定一个指针pre保存前一组的尾巴,然后连起来即可。对于第一组是个特殊情况,pre没有指向,那么就创造一个虚拟节点。

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        //增加一个虚设头节点
        ListNode* hair=new ListNode();
        hair->next=head;
        //pre指向上一组的末尾,初始化指向hari
        ListNode* pre=hair;
        //end用于指向每组的末尾(反转前是末尾,反转后是开头)
        ListNode* end=hair;
        while(end!=nullptr)
        {
            //首先让end找到末尾
            for(int i=0;i<k&&end!=nullptr;i++)  end=end->next;
            //如果末尾为空,表示这一组少于k个,因此不用反转
            if(end==nullptr)  break;
            //让上一组的末尾指向本组的开头(反转后end就是开头)
            pre->next=end;
            //更新pre指向本组反转后的末尾
            pre=head;
            //对本组进行翻转
            while(head!=end)
            {
                ListNode* tmp=head->next;
                head->next=end->next;
                end->next=head;
                head=tmp;
            }
            //更新
            end=pre;
            head=end->next;
        }
        return hair->next;

    }
};
posted @ 2021-07-28 16:22  曾凡璐  阅读(101)  评论(0)    收藏  举报