[路飞]_leetcode_25.K 个一组翻转链表

89 阅读1分钟

思考

题目要求:给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

示例1,中k=2,也就是每两个节点为一组做翻转。

那么我可以把K个一组的链表做为小链表,然后将所有链表首位拼接。

解题思路

  1. 确定链表长度,小于k个时,直接返回不需要任何操作
  2. 循环遍历链表,每k个执行一次翻转操作,然后做拼接
  3. 当遍历指针到达null 或者 剩余链表节点小于 k 的时候退出循环

定义 hair 虚拟头节点保留头指针,pre为待翻转小链表的头指针

pre
hair -> 1 -> 2 -> 3 -> 4 -> 5
pre ------> per != null
hair -> 2 -> 1 -> 3 -> 4 -> 5
            pre ----->pre
hair -> 2 -> 1 -> 4 -> 3 -> 5
                      pre ---->  pre
hair -> 2 -> 1 -> 4 -> 3 -> 5 -> null
                                 pre
hair -> 2 -> 1 -> 4 -> 3 -> 5 -> null

代码

var reverse = function (head, k) {
    let pre = head, cur = head, cnt = k;
    // 判断后续链表是否满足 k 个,如不满足直接返回
    while (--k && pre) {
        pre = pre.next;
    }
    if (!pre) return head;
    pre = null;
    while(cnt--) {
        // let next = cur.next;
        // cur.next = pre;
        // pre = cur;
        // cur = next;
        [cur.next, pre, cur] = [pre, cur, cur.next];
    }
    head.next = cur;
    return pre;
}
var reverseKGroup = function(head, k) {
    // 确定链表长度,小于k个时,直接返回不需要任何操作
    if (!head || k < 2) return head;
    let hair = new ListNode(-1, head), pre = hair;
    while (1) {
        // k 个一组的小链表做翻转
        pre.next = reverse(pre.next, k);
        // pre指针往下走 k 步以确定下一组的链表做翻转
        for (let i = 0; i < k && pre; i++) {
            pre = pre.next
        }
        // 但指针走到null节点代表循环结束
        if (!pre) break;
    }

    return hair.next;
};