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),每个节点都会被处理一次。

相关推荐
lzhdim5 小时前
AI的分类
人工智能·算法·机器学习·分类·数据挖掘
凤凰院凶涛QAQ8 小时前
《Java版数据结构 & 集合类剖析》Map & Set & 反射:“从哈希碰撞到红黑树转换,反射帮你扒开 HashMap 的桶数组看个究竟”
java·数据结构·算法
H.莓飛8 小时前
【数据结构】排序_OJ题(一):计数、桶与排序后的处理
java·开发语言·数据结构
wangchunyu1149 小时前
JAVA AQS与Lock实现原理(含CAS)
java·开发语言·word
w_zero_one10 小时前
算法--模拟
java·数据结构·算法
Javatutouhouduan10 小时前
阿里1658页Java面试题总结(含答案)
java·高并发·java面试·java面试题·后端开发·java程序员·java八股文
秋天的怀念_David11 小时前
算法一千零一夜 · 第十三夜 幻方,武侠世界里的数学迷宫
java·程序人生·算法
lll235269177911 小时前
HR如何快速整理面试沟通内容?
面试·职场和发展
专业程序开发源11 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
零售校长11 小时前
西湖区零售门店店长面试怎么准备
面试·职场和发展·零售