这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战
前言
关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!
题目描述
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 1:
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
示例 2:
输入: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;
}
};