力扣HOT100(31)K 个一组翻转链表

整体大思路:

把链表按 k 个节点分成一组一组,对每一组单独翻转,然后把翻转后的组和前后的组重新连接起来,最后不足 k 个的组不翻转。

我们只需要解决 3 个小问题:

  1. 怎么判断剩下的节点够不够 k 个?
  2. 怎么翻转一组 k 个节点?
  3. 怎么把翻转后的组和前后的组连接起来?

步骤 1:判断剩余节点是否够 k 个

我们用一个tail指针,从当前组的前驱节点pre开始,往前走 k 步:

  • 如果能走完 k 步,说明剩余节点够 k 个,可以翻转
  • 如果走不到 k 步就到nullptr了,说明不够,直接结束

步骤 2:翻转一组 k 个节点

这是 206 题「反转链表」的变种,我们需要翻转从headtail的子链表,并且返回翻转后的新头和新尾,方便后面连接。

步骤 3:把翻转后的组重新连接起来

这是这道题最关键的一步,翻转前一定要先保存下一组的头节点,不然会断链!

固定 4 步连接逻辑:

  1. 保存下一组的头:ListNode* nex = tail->next;
  2. 翻转当前组,得到新头和新尾:tie(newHead, newTail) = reverse(head, tail);
  3. 上一组的尾指向新头:pre->next = newHead;
  4. 新尾指向下一组的头:newTail->next = nex;

然后更新指针,准备处理下一组:

  • pre = newTail;(下一组的前驱是当前组的新尾)
  • head = nex;(下一组的头是之前保存的 nex)
cpp 复制代码
/**
 * 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:
    //写一个pair类型的 函数 翻转一个子链表,并返回新的头和尾
    //pair容器用于存放成对出现的 可以返回新生成的pair.first pair.second
    pair<ListNode*,ListNode*> myReverse(ListNode* head,ListNode* tail){
        ListNode* prev = tail->next;
        ListNode* p = head;
        while(prev != tail){
            //反转链表
            ListNode* nex = p->next;//p的下一个存在nex中
            p->next = prev;
            prev = p;
            p = nex;

        }
        return {tail,head};//返回新的头 和尾巴
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* hair = new ListNode (-1,head);
        ListNode* pre =  hair;

        while(head){
            ListNode* tail  = pre;//尾指针 用来判断剩余部分还有k个吗。初始在虚拟头
            for(int i = 0; i<k;i++){
                tail = tail->next;//tail一直往前走
                if(tail == nullptr){//走到空说明不满足k步了 直接返回 终止循环
                    return hair->next;
                }
            }
            //现在就是满足k步的
            ListNode * nex = tail->next;//tail现在的位置在第k个元素
            //接下来调用函数 进行翻转
            
           tie(head, tail) = myReverse(head, tail);


            //子链表重新接回去
            pre->next = head;
            tail->next = nex;
            pre = tail;//用来存放下一组头的前驱
            head = tail->next;//开始前移
        }
        return hair->next;
    }
};
相关推荐
gis开发之家18 分钟前
《Vue3 从入门到大神40篇》Vue3 源码详解(十):diff 算法全解析 —— 为什么 Vue3 比 Vue2 更快?
javascript·算法·typescript·前端框架·vue3·vue3源码
进击的丸子23 分钟前
虹软人脸服务器SDK-C++语言Demo实操指南
后端·算法
兰令水44 分钟前
hot100【acm版】【2026.7.25/26打卡-java版本】
java·算法·排序算法
音视频工程实战1 小时前
PromptQL 新手入门与实战指南
数据库·sql·算法
wabs6662 小时前
关于图论【卡码网104.建造最大岛屿的思考】
数据结构·算法·图论
玖玥拾2 小时前
LeetCode 27 移除元素
算法·leetcode
冻柠檬飞冰走茶3 小时前
PTA基础编程题目集 7-15 计算圆周率(C语言实现)
c语言·开发语言·数据结构·算法
问商十三载3 小时前
AI 引擎生成式优化两种思路怎么选?2026 对比分析附选型方法
人工智能·算法
hanlin034 小时前
刷题笔记:力扣第704、977、209题(数组相关)
笔记·算法·leetcode