LeetCode系列记录我学习算法的过程。
持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 24 天,点击查看活动详情
题目
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例:
输入: head = [1,2,3,4,5], k = 2
输出: [2,1,4,3,5]
输入: head = [1,2,3,4,5], k = 3
输出: [3,2,1,4,5]
提示
- 链表中的节点数目为
n 1 <= k <= n <= 50000 <= Node.val <= 1000
思路
这题是每 k 项为一组进行重复的翻转操作,那也可以用递归的方法来实现,首先是找到递归结束的条件
即当结点只剩一个,或没有结点时,递归结束,返回自身
- 定义变量
arr存储要翻转的结点,temp暂存head res为最后的结果,tick指向res的尾结点- 首先遍历链表往
arr存储k个结点 - 判断存储结点数是否满足
k, 不满足直接将暂存的temp拼接到tick后 - 满足则从后往前取出
arr里的结点依次拼接到tick后,然后将剩余结点递归调用函数 - 最后返回
res.next
代码实现
/**
* 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 || !head.next) return head
// arr存储要翻转的结点,temp暂存head
const arr = [], temp = head
// res为最后返回的结果,tick指向尾结点
let res = new ListNode(), tick = res
// 遍历存储 k 个结点
while(arr.length < k && head) {
arr.push(head)
head = head.next
}
// 存储结点数满足 k
if (arr.length === k) {
// 从后往前取出arr里的结点连接到res后
while(arr.length) {
const item = arr.pop()
tick.next = item
tick = tick.next
}
// 将剩下的结点递归调用reverseKGroup
tick.next = reverseKGroup(head, k)
} else {
// 结点数不满k,不翻转直接拼接
tick.next = temp
}
return res.next
};
优化
中间的循环在碰到结点为空时就可以直接返回结果,后续也不用在判断 arr 的长度和 k 了
var reverseKGroup = function(head, k) {
if(!head || !head.next) return head
const arr = []
let res = new ListNode(), tick = res, temp = head
while(arr.length < k) {
if (!temp) return head
arr.push(temp)
temp = temp.next
}
while(arr.length) {
const item = arr.pop()
tick.next = item
tick = tick.next
}
tick.next = reverseKGroup(temp, k)
return res.next
};