LeetCode 25题是“K 个一组翻转链表”,要求我们将链表中的节点每 K 个一组翻转,并返回翻转后的链表。下面是一个可能的Java解法,附有详细注释和思路总结。
// 定义链表节点类
class ListNode {
int val; // 节点的值
ListNode next; // 指向下一个节点的指针
ListNode(int x) { val = x; } // 构造方法
}
public class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
// 创建一个虚拟头节点,简化链表操作
ListNode dummy = new ListNode(0);
dummy.next = head;
// prevGroupEnd指向上一个已翻转子链表的结尾
ListNode prevGroupEnd = dummy;
while (true) {
// 找到当前组的第k个节点
ListNode kthNode = getKthNode(prevGroupEnd, k);
// 如果不足k个节点,则不翻转,退出循环
if (kthNode == null) {
break;
}
// 记录下一个组的开始节点
ListNode nextGroupStart = kthNode.next;
// 翻转当前组的链表
ListNode prev = nextGroupStart;
ListNode curr = prevGroupEnd.next;
while (curr != nextGroupStart) {
// 保存下一个节点
ListNode temp = curr.next;
// 当前节点指向前一个节点,进行翻转
curr.next = prev;
// 移动prev和curr指针
prev = curr;
curr = temp;
}
// 连接翻转后的部分
ListNode temp = prevGroupEnd.next; // 记录当前组的第一个节点
prevGroupEnd.next = kthNode; // 组前节点指向翻转后的头
prevGroupEnd = temp; // 更新prevGroupEnd为当前组的结尾
}
// 返回新的头节点
return dummy.next;
}
// 获取从start节点开始的第k个节点
private ListNode getKthNode(ListNode start, int k) {
while (start != null && k > 0) {
start = start.next; // 移动到下一个节点
k--; // 减少计数
}
// 返回第k个节点或null(如果不足k个)
return start;
}
}
思路总结:
-
虚拟头节点:使用一个虚拟头节点简化边界条件的处理,特别是在操作链表头部时。
-
指针操作:使用多个指针来追踪需要翻转的部分和已经翻转的部分。
prevGroupEnd
是上一个翻转组的结尾,kthNode
找到当前组的结尾。 -
翻转逻辑:在每一组中,使用常规的链表翻转方法进行局部翻转。
-
连接翻转后的部分:在完成一组的翻转后,重新连接翻转后的部分,准备处理下一组。
-
结束条件:如果不足k个节点,直接退出循环,因为不需要翻转。
通过这些步骤,我们可以实现每K个节点的翻转操作。