【力扣题解】LeetCode 25. K 个一组翻转链表

文章目录


🔥 个人主页:铁皮哥(欢迎关注)

📌 作者简介:28届校招生,后端开发/Agent 方向在学

📚 学习内容:Java、Python、计算机视觉、大语言模型、Agent开发

📝 专栏内容:从零开始的Claude Code零代码生活(持续更新中)

✨不只背八股,更想搞懂为什么这样设计


前言

这道题总是容易卡住,关键是指针有点多,需要考虑的边界有点多,记录一下。

一、题目分析

这道题看上去和 LeetCode 206. 反转链表很相似,实际上 206 就是本题当 k = 链表长度时的情况。

本题核心难点不是"反转链表",而是如何按组反转,并把每一组和前后链表重新接好。

我们可以把链表分成若干段:

上一段尾部 -> [当前要翻转的 k 个节点] -> 下一段头部

每次只处理一组长度为 k 的区间。

假设当前链表是:

dummy -> 1 -> 2 -> 3 -> 4 -> 5

如果 k = 3,当前要翻转的是:

1 -> 2 -> 3

翻转后变成:

3 -> 2 -> 1

然后重新接回原链表:

dummy -> 3 -> 2 -> 1 -> 4 -> 5

这里有几个关键指针:

groupPrev:当前组前一个节点

kth:当前组第 k 个节点

groupNext:当前组后面的第一个节点

二、解法

题目最终要返回头节点,我们先在 head 前自行接一个 dummy 节点,最后我们返回的答案就是 dummy.next

java 复制代码
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;

        return dummy.next;
        
    }
}

来看之前提到的关键指针 groupPrev,最开始应该被这样初始化,因为第一组的前一个结点就是 dummy

java 复制代码
ListNode groupPrev = dummy;

下一步我们要扩一个大循环,在里面完成 k 个一组的翻转链表,具体是这样的思路:

java 复制代码
while(true){
//1. 找到当前翻转组的第 K 个结点,即关键结点 kth
//第 K 个结点的下一个结点就是关键结点 groupNext

//2.按照力扣 206 的思路去翻转从 groupPrev.next 到 kth 的链表

//3.把翻转后的链表正确接回原链表
           
}

先来实现找到第 k 个结点的方法,这里很简单,就是逐层 k--,直到 k = 0node 先变成 null 的时候退出。要考虑:node == null 其实就意味着剩余结点数量已经不足 k 个了,可以退出主函数中的大循环了。

java 复制代码
private ListNode getKth(ListNode node, int k){
	while(node != null && k != 0){
		node = node.next;
		k--;
	}
	return node;
}

所以循环 while(true) 的终止条件,肯定是当剩余链表的数量已经不足 k 个时退出,可以写成这样:

java 复制代码
ListNode kth = getKth(groupPrev, k);
if(kth == null){
	break;
}

下一步去翻转从 groupPrev.nextkth 的链表。
groupNext 的语义是当前组的下一个结点。

其他操作就和力扣 206 的思路是一样的,唯一不同的是 while 的终止条件不是 cur != null,而是 cur != groupNext,这是因为我们最多只能翻转 k 个结点,如果终止条件设为 cur != null,那就会翻转从当前一直到尾部的所有结点了。

java 复制代码
ListNode groupNext = kth.next;
ListNode prev = groupNext;
ListNode cur = groupPrev.next;
while(cur != groupNext){
	ListNode temp = cur.next;
	cur.next = prev;
	prev = cur;
	cur = temp;
}

翻转完这 k 个结点后,下一步是把当前处理好的结点组接回原链表。

oldGroupHead 指向的是"翻转前"的当前组的头结点,目前已经变成了当前组的尾结点,先把这个值暂存起来。
kth 经过翻转,已经从原先的尾结点变成了当前组的新头结点,所以 groupPrev.next = kth 的意思是:让该组前一个节点的 next 指向这个新的头结点。

然后再把 groupPrev 移动到之前暂存的 oldGroupHead,因为它现在是当前组的尾结点,下一轮要从它后面继续处理。

java 复制代码
ListNode oldGroupHead = groupPrev.next;
groupPrev.next = kth;
groupPrev = oldGroupHead;

最终整体代码呈现如下:

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;

        ListNode groupPrev = dummy;
        while(true){
            ListNode kth = getKth(groupPrev, k);
            if(kth == null){
                break;
            }
            ListNode groupNext = kth.next;
            ListNode prev = groupNext;
            ListNode cur = groupPrev.next;
            while(cur != groupNext){
                ListNode temp = cur.next;
                cur.next = prev;
                prev = cur;
                cur = temp;
            }
            ListNode oldGroupHead = groupPrev.next;
            groupPrev.next = kth;
            groupPrev = oldGroupHead;

        }

        return dummy.next;
        
    }
    private ListNode getKth(ListNode node, int k){
        while(node != null && k != 0){
            node = node.next;
            k--;
        }
        return node;
    }
}

写在文后

期待您的一键三连!如果有什么问题或建议欢迎在评论区交流!

相关推荐
小新同学^O^1 小时前
简单学习 --> 单例模式
java·学习·多线程
Henray20241 小时前
LRU缓存设计与实现
java·面试
lbb 小魔仙1 小时前
告别腾讯会议40分钟限制:用ToDesk协作版开在线会议,免费不限时远程会议新方案
python·langchain·jenkins
凯瑟琳.奥古斯特1 小时前
PyTorch动态计算图详解
人工智能·pytorch·python·深度学习
一个数据大开发2 小时前
企业知识工程的三条路线:Neo4j 知识中台、Agent + Action 与本体原生 Runtime
大数据·python·neo4j
甲方大人请饶命2 小时前
SSM-基础
java·数据库·spring
ZOOOOOOU2 小时前
云平台赋能门禁终端,打造智慧社区一体化管理
大数据·数据结构·架构
谷雨不太卷2 小时前
Linux基础IO
java·开发语言
QiZhang | UESTC2 小时前
windows IDE里kimi code问题修复
windows