【路飞】leetcode-25. k个一组翻转链表

201 阅读1分钟

加油 第 6 练

25. K 个一组翻转链表

题目描述:给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

方法一:递归

每次反转前 k 个元素,不足 k 个不反转,第一次反转后返回的节点即为头节点

// 反转[a,b) 区间链表,左闭右开
var reverseList = function (a, b) {
    let prev = null, cur = a;
    while (cur != b) {
        [cur.next, prev, cur] = [prev, cur, cur.next];
    }
    return prev; //返回反转后的头节点
};
var reverseKGroup = function (head, k) {
    let a = head, b = head;
    //   查看链表长度是否 >= k,不足k 不需要反转
    for (let i = 0; i < k; i++) {
        if (!b) {
            return head
        }
        b = b.next
    }
    //   k个元素一组进行反转
    let nHead = reverseList(a, b)
    a.next = reverseKGroup(b, k)
    return nHead
};

方法二:迭代

  • 将链表k个一分组(指定指针每次移动k),每个分组判断长度,决定是否反转
  • 分组子链表头节点 head,还需要有 head 的上一个节点 pre,以便翻转完后把子链表再接回 pre
  • 反复移动指针 head 与 pre,对 head 所指向的子链表进行翻转,直到结尾
var reverseKGroup = function (head, k) {

    var reverseList = function (head, tail) {
        let prev = tail.next;
        let p = head;
        while (prev !== tail) {
            // const nex = p.next;
            // p.next = prev;
            // prev = p;
            // p = nex;
            [p.next,prev,p] = [prev,p,p.next]
        }
        return [tail, head];
    };

    const _Node = new ListNode(0);
    _Node.next = head;
    let pre = _Node;

    while (head) {
        let tail = pre;
        for (let i = 0; i < k; i++) {
            tail = tail.next
            if (!tail) {
                return _Node.next
            }
        }

        const nex = tail.next;
        [head, tail] = reverseList(head, tail);
        // 把子链表重新接回原链表
        pre.next = head;
        tail.next = nex;
        pre = tail;
        head = tail.next;
    }

    return _Node.next
};