链表——K个一组翻转链表

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

1.整体思路

  • 虚拟头节点避免边界问题
  • 每k个节点截成一段
  • 翻转这一段
  • 把翻转后的段重新接回原链表
  • 不足k个就停止

2.关键变量

  • pre:当前要翻转组的前一个节点
  • start:当前组第一个节点
  • end:当前组最后一个节点
  • next:下一组的第一个节点

3.执行流程
1.找到k个节点
2.切断与后面的连接
3.翻转这k个节点
4.重新连接前后链表
5.继续下一组

示例演示
输入:1->2->3->4->5,k=2
输出:2->1->4->3->5
执行过程:
第一组:1,2 → 翻转 → 2,1
第二组:3,4 → 翻转 →4,3
剩余:5 → 不翻转
最终:2->1->4->3->5

完整代码实现如下:
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) {

    // 1. 定义虚拟头节点,方便处理头部翻转
    ListNode dummy = new ListNode(0);
    dummy.next = head;

    // pre 指向每组的前驱节点,end 指向每组的最后一个节点
    ListNode pre = dummy;
    ListNode end = dummy;

    // 2. 循环:直到无法再取出 k 个节点
    while (end.next != null) {
        // 让 end 向后走 k 步,找到当前组的末尾
        for (int i = 0; i < k && end != null; i++) {
            end = end.next;
        }
        // 如果 end == null,说明剩余节点不足 k 个,直接退出
        if (end == null) break;

        // 3. 截取要翻转的片段
        ListNode start = pre.next;     // 本组要翻转的第一个节点
        ListNode next = end.next;       // 保存下一组的头节点

        // 4. 断开本组与下一组的连接,翻转本组链表
        end.next = null;
        pre.next = reverse(start);      // 翻转后,pre 指向新头

        // 5. 把翻转后的链表与后面的链表接上
        start.next = next;

        // 6. 更新 pre 和 end,准备处理下一组
        pre = start;
        end = pre;
    }

    return dummy.next;
}

// 翻转单组链表(普通翻转)
private ListNode reverse(ListNode head) {
    ListNode pre = null;
    ListNode cur = head;
    while (cur != null) {
        ListNode next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}

}

要注意java原生的ListNode链表类本身没有内置的reverse()方法,所以必须自己手动实现翻转逻辑,不能直接调用。

为什么不能直接用?
Java 标准库中:

  • Collections.reverse() 只能翻转 List 集合(如 ArrayList、LinkedList),不能直接作用于自定义的链表节点 ListNode

  • 你写的是自定义单向链表,JDK 没有提供现成的翻转方法,必须自己写翻转逻辑

注意:
Java 里可以直接写 null,而且必须小写!
Java 没有 NULL、没有 nullptr,只有 null。

Java vs C++ 对比

  1. C++
  • NULL → 宏,本质是 0
  • nullptr → C++11 空指针(真正的空指针类型)
  • 不能写 null(会报错)
  1. Java
  • 只有 null(小写)
  • 表示空引用
  • 没有大写 NULL
  • 没有 nullptr

Java中main方法必须写在类内

为什么 return dummy.next 是正确的?

dummy的唯一作用就是固定链表的入口,dummy.next永远指向整个链表的真正头节点

一开始:
ListNode pre = dummy;
pre.next = reverse(start);

所以:

  • pre就是dummy
  • pre.next = 新头
    等价于
    dummy.next = 新头

也就是说:
翻转后的新头节点,直接挂在了dummy后面

posted @ 2026-04-09 19:45  AlexXuu  阅读(1)  评论(0)    收藏  举报