leetcode25(困难)——K个一组翻转链表

211 阅读2分钟
  • 思路

    • 一、判断长度是否大于K

      • 是 =》 进行第二步
      • 否 =》返回原链表hair.next

        • ***注意:设计的虚拟头节点hair,无论翻转与否,hair.next会 始终指向原链表的头节点
    • 二、翻转

      • 2.1反转链表:myReverse(head, tail) { return [tail, head]}

        • 核心代码同leetcode206题一致
      • 2.2 子链表之家的头尾连接

        • 子链表的头部与上一个子链表连接

          • 出现一个问题——第一个子链表没有head之前的节点与之连接?? =》创建pre

            • 代码: pre.next = head
        • 子链表的尾部与下一个子链表连接

          • 代码:tail.next = nex
      • 2.3 翻转顺序

        • 1、创建一个虚拟头节点
        • 2、循环翻转子链表

          • 1、确定第一组end/tail的位置

            • let end = start
            • end = end.next
          • 2、用nex指针指着第二组的head

            • const nex = end.next
          • 3、调用myReverse(head, end)
          • 4、首尾相连

            • start.next = head
            • tail.next = nex
          • 5、更新start、head

            • start = end
            • head = nex
        • 3、返回hair.next
    • 代码展示
/**
 * 反转 k 个一组的链表
 * @param {ListNode} head - 链表的头节点
 * @param {number} k - 每组的大小
 * @return {ListNode}
 */
var reverseKGroup = function(head, k) {
    // 定义反转函数 myReverse,接收头节点和尾节点,返回反转后的头尾节点
    const myReverse = (head, end) => {
        let prev = null; 
        let cur = head;
        let temp = null
        // 迭代反转链表
        while (prev !== end) {
            temp = cur.next; // 记录当前节点的下一个节点
            cur.next = prev; // 将当前节点的 next 指向前一个节点
            prev = cur; // 更新 prev 为当前节点
            cur = temp; // 更新当前节点为原先记录的下一个节点
        }
        return [end, head]; // 返回反转后的头尾节点
    }

    const hair = new ListNode(0); // 创建一个虚拟头节点
    hair.next = head; // 将虚拟头节点的 next 指向原链表头节点
    let start = hair; // 初始化 start 为虚拟头节点

    while (head) {
        let end = start;
        // 查看剩余部分长度是否大于等于 k
        for (let i = 0; i < k; ++i) {
            end = end.next; // 移动 end 指针
            if (!end) {
                return hair.next; // 剩余长度小于 k,直接返回原链表
            }
        }
        const nex = end.next; // 记录反转区域的下一个节点
        [head, end] = myReverse(head, end); // 反转当前 k 个节点
        // 把子链表重新接回原链表
        start.next = head; // 将虚拟头节点的 next 指向反转后的头节点
        end.next = nex; // 反转后的尾节点指向反转区域的下一个节点
        start = end; // 更新 start 为反转后的尾节点
        head = nex; // 更新 head 为反转区域的下一个节点
    }
    return hair.next; // 返回虚拟头节点的 next,即反转后的链表头节点
};