LeetCode 25:K 个一组翻转链表

LeetCode 25:K 个一组翻转链表

题目思路

这道题要求每 k 个节点翻转一次,如果最后剩余节点不足 k 个,则保持原顺序。

我的第一反应不是直接操作链表指针,而是利用 Deque(双端队列)暂存当前这一组节点。

核心思路:

  1. 先从当前 head 开始,最多取 k 个节点放入 Deque。

  2. 如果不足 k 个,说明已经到了最后一组,直接返回原链表。

  3. 如果刚好取到 k 个:

    • 通过 pop() 依次取出节点;
    • 因为前面使用的是 push(),所以取出的顺序正好是原来的逆序;
    • 将这些节点重新连接起来。
  4. 当前这一组处理完之后,对剩余链表 flag 递归执行相同操作。

代码如下:

java 复制代码
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        Deque<ListNode> deque = new ArrayDeque<>();

        ListNode flag = head;
        int num = 0;

        // 先收集 k 个节点
        while (flag != null && num < k) {
            deque.push(flag);
            flag = flag.next;
            num++;
        }

        // 当前节点数量不足 k,保持原顺序
        if (num == k) {
            ListNode newHead = deque.pop();
            head = newHead;

            // 按逆序重新连接
            for (int i = 2; i <= k; i++) {
                newHead.next = deque.pop();
                newHead = newHead.next;
            }

            // 当前组处理完成,递归处理后面的节点
            newHead.next = reverseKGroup(flag, k);

        } else {
            return head;
        }

        return head;
    }
}

最关键的地方:为什么 push() + pop() 就能实现翻转?

假设:

text 复制代码
1 -> 2 -> 3

依次执行:

java 复制代码
deque.push(1);
deque.push(2);
deque.push(3);

队列内部相当于:

text 复制代码
3
2
1

之后依次:

java 复制代码
deque.pop();

得到:

text 复制代码
3 -> 2 -> 1

所以这里实际上是借助 Deque 的**栈特性(后进先出,LIFO)**完成了当前 k 个节点的逆序。

flag 的作用

这里:

java 复制代码
ListNode flag = head;

flag 相当于一个"探路指针"。

收集节点时:

java 复制代码
while(flag != null && num < k){
    deque.push(flag);
    flag = flag.next;
    num++;
}

当循环结束后,如果:

text 复制代码
1 -> 2 -> 3 -> 4 -> 5
        ↑
       flag

假设 k = 3,那么当前组是:

text 复制代码
1 -> 2 -> 3

而 flag 已经指向:

text 复制代码
4 -> 5

所以当前组翻转完成后:

java 复制代码
newHead.next = reverseKGroup(flag, k);

实际上就是:

text 复制代码
3 -> 2 -> 1 -> 4 -> 5
             ↑
          递归处理

为什么不足 k 个时直接返回?

这是题目的要求:

如果最后剩余的节点不足 k 个,就保持原顺序。

例如:

text 复制代码
1 -> 2 -> 3 -> 4 -> 5
k = 3

第一次处理:

text 复制代码
1 -> 2 -> 3

翻转成:

text 复制代码
3 -> 2 -> 1

剩下:

text 复制代码
4 -> 5

只有 2 个节点,不满足 k = 3,因此:

java 复制代码
if(num == k){
    ...
}else{
    return head;
}

直接返回:

text 复制代码
4 -> 5

最终:

text 复制代码
3 -> 2 -> 1 -> 4 -> 5

这道题的收获

这道题我采用的是:

Deque + 递归

而不是直接进行复杂的链表指针翻转。

这种写法的优点是思路比较直观:先把一组节点"存起来",再按照逆序重新连接。

需要注意的是,这种方法会额外使用 O(k) 的空间。

如果追求这道题的最优空间复杂度,可以进一步学习纯链表指针操作 的写法,把额外空间降低到 O(1)。不过从理解和实现难度来说,目前这个版本已经能够很好地完成题目要求。

时间复杂度为 O(n),每个节点都会被处理一次。

相关推荐
阿狗童鞋15 小时前
数据结构与算法实战指南
数据结构·算法
码上有光15 小时前
Linux:进程间通信——匿名管道通信、命名管道通信
android·java·linux·linux通信·匿名通信·命名通信
落魄实习生16 小时前
Agent Scope Java 2.x 系列【11】AgentState 与状态存储
java·开发语言·ai
Navigator_Z16 小时前
LeetCode //C - 1275. Find Winner on a Tic Tac Toe Game
c语言·算法·leetcode
未来之窗软件服务16 小时前
递归时间复杂度演算T (n)=aT (n/b)+f (n)-东方仙盟
算法·仙盟创梦ide·东方仙盟
Ivanqhz16 小时前
干涉图着色
java·服务器·网络·数据库·人工智能·深度学习
垆边人似月.16 小时前
华为机考题:明明的随机数
数据结构·算法·华为
我命由我1234517 小时前
Photoshop - 将Photoshop图像置入其他应用程序
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
Doubbbbbbble云17 小时前
多维空间索引结构R树与KD树性能对比研究4
算法
海上小飞龙17 小时前
【KMP算法-中篇】next 数组的递推:往前填一位,靠的是往回退几步
算法