LeetCode 25 Reverse Nodes in k-Group(Tag:Linked List Difficulty:Hard)

232 阅读2分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

前言

关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!

题目描述

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

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

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

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

示例 1:

image.png

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例 2:

image.png

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

示例 3:
输入:head = [1,2,3,4,5], k = 1
输出:[1,2,3,4,5]

示例 4:
输入:head = [1], k = 1
输出:[1]

链接:leetcode-cn.com/problems/re…

题解

这道题目的核心是链表节点交换。完成一个链表的逆转,一般只需要新的尾节点和新的头节点就可以了。

我们首先定义一个假头,作为新的头节点,用 cur 指向当前的 head 作为新的尾节点。交换的过程只需要模拟一下就好了。重点在于,如何找到这 k 个节点。

做法是先遍历一遍所有节点找出这个链表的长度,然后以 k 为 step 来遍历链表。

具体代码如下,时间复杂度为 O(n)

/**
 * 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) {
    if (!head || k === 1) return head;
    let dummy = new ListNode(0)
    dummy.next = head;
    let len = 1;
    // 计算链表长度
    while (head = head.next) len++;
    let pre = dummy;    
    // 以 k 为 step 来交换
    for (let l = 0; l + k <= len; l += k) {
      let cur = pre.next;
      let nxt = cur.next;
      for (let i = 1; i < k; ++i) {
        cur.next = nxt.next;
        nxt.next = pre.next;
        pre.next = nxt;
        nxt = cur.next;
      }
      pre = cur;
    }
    return dummy.next;
  }
};