开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
描述
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
数据范围: \ 0 \le n \le 2000 0≤n≤2000 , 1 \le k \le 20001≤k≤2000 ,链表中每个元素都满足 0 \le val \le 10000≤val≤1000
要求空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
例如:
给定的链表是 1\to2\to3\to4\to51→2→3→4→5
对于 k = 2k=2 , 你应该返回 2\to 1\to 4\to 3\to 52→1→4→3→5
对于 k = 3k=3 , 你应该返回 3\to2 \to1 \to 4\to 53→2→1→4→5
示例1
输入:
{1,2,3,4,5},2
返回值:
{2,1,4,3,5}
示例2
输入:
{},1
返回值:
{}
算法思想一:栈
解题思路:
利用栈的先进后出规则实现链表的翻转
1、首先遍历链表k个结点入栈,若k大于链表的长度则直接返回链表不翻转
2、栈内结点出栈(翻转)
3、判断剩下的链表个数够不够k个(少于k个不需要反转,大于k个重复 1、2步骤)
4、将已翻转的部分与剩下的链表连接起来
代码
class Solution:
def reverseKGroup(self , head , k ):
# write code here
# 用于链表头元素
Phead = ListNode(None)
p = Phead
while True:
count = k
stack = []
tmp = head
# 进栈
while count and tmp:
stack.append(tmp)
tmp = tmp.next
count -= 1
# 跳出上面循环,tmp是第k+1的元素
# 如果循环结束,count不为0,则代表不足k个元素
if count:
p.next = head
break
# 对k个元素进行反转
# 出栈
while stack:
p.next = stack.pop()
p = p.next
# 与剩下链表链接起来
p.next = tmp
head = tmp
return Phead.next
算法思想二:递归
解题思路:
1、找到待翻转的k个节点(注意:若剩余数量小于 k 的话,则不需要反转,因此直接返回待翻转部分的头结点即可)。
2、对其进行翻转。并返回翻转后的头结点(注意:翻转为左闭又开区间,所以本作的尾结点其实就是下一作的头结点)。
3、对下一轮 k 个节点也进行翻转操作。
4、将上一轮翻转后的尾结点指向下一轮翻转后的头节点,即将每一轮翻转的k的节点连接起来。
/**
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
public ListNode reverseKGroup (ListNode head, int k) {
// write code here
ListNode cur = head;
int count = 0;
// 找到待反转的第k个结点
while (cur != null && count != k) {
cur = cur.next;
count++;
}
if (count == k) {
// 递归
cur = reverseKGroup(cur, k);
// 反转列表
while (count != 0) {
count--;
ListNode tmp = head.next;
head.next = cur;
cur = head;
head = tmp;
}
// 拼接后续的链表
head = cur;
}
return head;
}
}