K个一组翻转链表

95 阅读1分钟

K个一组翻转链表

要求

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

进阶: 可以设计一个只使用常数额外空间的算法来解决此问题吗? 不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

思路

思路都写在代码注释里啦

代码

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function (head, k) {
    // 举例:1->2->3->4->5->6->7->8->9 k=4
    // 当传进来的head为空,直接return出去
    if (!head) return null;
    // 创建两个指针,指向head的前一个节点
    let ret = new ListNode(-1, head),
        pre = ret;
    do {
        // 第一次翻转
        // 此时,链表为:-1(ret,pre)->1->2->3->4->5->6->7->8->9
        // pre.next = reverse(1->2->3->4,4)
        // 经过reverse函数的处理,链表为:-1(ret,pre)->4->3->2->1->5->6->7->8->9
        pre.next = reverse(pre.next, k);
        // i<k且pre不为空,一直for
        for (let i = 0; i < k && pre; i++) {
            pre = pre.next;
        }
        // pre为空,跳出循环
        if (!pre) break;
        // for出来后,链表为-1(ret)->4->3->2->1(pre)->5->6->7->8->9
    } while (1)
    // 循环结束,链表为-1(ret)->4->3->2->1->8->7->6->5->9
    return ret.next;
};

var reverse = function (head, n) {
    let pre = head,
        cur = head,
        con = n;
    // 此处while为了判断传入的链表是否够n值翻转
    while (--n && pre) {
        pre = pre.next;
    }
    // 不够n值翻转,return传进来的值
    if (!pre) return head;
    // 满足n值翻转,设pre为null,进行解构赋值
    pre = null;
    while (con--) {
        [cur.next, pre, cur] = [pre, cur, cur.next]
    }
    // 经过while里面的解构赋值处理,此时的cur指向5
    // 此处head.next = cur,即为:1.next = 5
    head.next = cur;
    // return 4 (此时链表关系为:4->3->2->1->5)
    return pre;
}