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

102 阅读3分钟

题目介绍

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

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

进阶:

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

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

自己的思路比较混乱,虽然也可以提交通过,但是实在写的比较差,就是用二维数据,记录需要反转的节点,尾部节点的连接,然后再遍历二维数据进行反转,把每个二维数组的头部和尾部相连即可

function reverseList(head) {
    if(!head) return null
    let cur = head
    let pre = null // 这里会组成一个新的链表返回
    //  1 => 2 = 3 => 4 => 5
    while(cur) {
        // 暂存下一个节点
        let nex = cur.next
        // 这里断开了之前的next节点,设置为上一个节点
        cur.next = pre
        // 
        pre = cur
        cur = nex

    }
    return pre
}
var reverseKGroup = function(head, k) {
    if (!head) return null
    let arrList = []
    let arr = []
    let arr3 = []
    let j = 0

    for (let i = 0; i <= k; i++) {
        if (!head) break
        if (i === k) {
            i = 0
            arrList.push(arr)
            arr[arr.length - 1].next = null
            arr3.push([arr[arr.length - 1], arr[0]])
            arr = []
        }
        arr.push(head)
        head = head.next
    }
    if (arr.length === k) {
        arrList.push(arr)
        arr3.push([arr[arr.length - 1], arr[0]])
    }
    for (let i = 0 ; i < arrList.length; i++) {
        reverseList(arrList[i][0])
    }
    for (let i = 0; i < arr3.length - 1; i++) {
        arr3[i][1].next = arr3[i + 1][0]
    }
    if (arr.length !== k && arr.length) {
        arr3[arr3.length - 1][1].next = arr[0]
    }
    return arr3[0][0]
};

转LeetCode上大神的解题思路,个人感觉这个比较好理解

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

作者:reals 链接:leetcode-cn.com/problems/re… 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

function reverseList(head) {
    if(!head) return null
    let cur = head
    let pre = null
    while(cur) {
        let nex = cur.next
        cur.next = pre
        pre = cur
        cur = nex
    }
    return pre
}



var reverseKGroup = function(head, k) {
    if (k === 1) return head
    // 虚拟节点
    let dummy = new ListNode(-1, head)
    // 
    let pre = dummy
    let end = dummy
    while(end.next) {
        for (let i = 0; i < k && end; i++) {
            end = end.next
        }
        if (end === null) break
        // 找到需要反转的头部
        let start = pre.next
        // 暂存下一个节点
        let next = end.next
        // 断开连接
        end.next = null
        // reverseList会返回新的头部
        pre.next = reverseList(start)
        // 之前的头变成了尾部,所以重新建立 下一个节点的连接
        start.next = next
        // 记录上一次反转的尾部
        pre = start // 2
        // 下一次反转开始的位置
        end = pre
    }
     return dummy.next
};