WELCOME TO Pluto134340小行星

清风湿润,茶烟轻扬。

31.K 个一组翻转链表

 25. K 个一组翻转链表

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

步骤分解:

链表分区为已翻转部分+待翻转部分+未翻转部分
每次翻转前,要确定翻转链表的范围,这个必须通过 k 此循环来确定
需记录翻转链表前驱和后继,方便翻转完成后把已翻转部分和未翻转部分连接起来
初始需要两个变量 pre 和 end,pre 代表待翻转链表的前驱,end 代表待翻转链表的末尾
经过k此循环,end 到达末尾,记录待翻转链表的后继 next = end.next
翻转链表,然后将三部分链表连接起来,然后重置 pre 和 end 指针,然后进入下一次循环
特殊情况,当翻转部分长度不足 k 时,在定位 end 完成后,end==null,已经到达末尾,说明题目已完成,直接返回即可

image

 【对着图像看代码】

public ListNode reverseKGroup(ListNode head, int k) {
    ListNode dummy = new ListNode(0);       // 此处只是设置一个哨兵节点
    dummy.next = head;      // 哨兵节点的下一个指向首节点

    ListNode pre = dummy;       // 上一段的最后一个节点 节点初始化
    ListNode end = dummy;       // 本段最后一个节点

    while (end.next != null) {
        // 此处是为了找到其中的 k 个子节点
        for(int i = 0 ; i < k && end != null; i++){
            end = end.next;
        }

        if(end == null){        // 如果直接到头了,那就说明没有满足 k 个
            break;
        }

        ListNode start = pre.next;           // 此处是为记录原始未反转段的起始节点
        ListNode nextStart = end.next;       // 记录下一个阶段  起始点

        end.next = null;                // 此处是为了进行后面的反转操作,断开此处链接,让后面反转操作知道截断点在哪里
        pre.next = reverse(start);      // 反转操作

        start.next = nextStart;         // 反转之后,start节点实际是已经最后一个节点了,为了和后面的划分段链接,让他的下一个节点连接上下一段的起始点即可
        pre = start;                    // pre再次来到下一段的上一个节点,也就是本段的结尾点
        end = pre;                      // 结束点,准备开始下一段的循环找 k 长度的段操作
        
    }

    return dummy.next;           // 返回最开始的哨兵
}

private ListNode reverse(ListNode head){
    ListNode pre = null;
    ListNode curr = head;

    while(curr != null){        // 交换操作
        ListNode next = curr.next;
        curr.next = pre;
        pre = curr;
        curr = next;
    }

    return pre;     // 返回哨兵,此处是新的翻转序列的起始节点
}
View Code

作者:房建斌学算法 来源:力扣(LeetCode)

posted @ 2026-01-23 10:14  Pluto134340  阅读(1)  评论(0)    收藏  举报