0025. K 个一组翻转链表
大约 4 分钟
---
0025. K 个一组翻转链表
- 标签:递归、链表
- 难度:困难
题目链接
题目大意
描述:给你链表的头节点 head ,再给定一个正整数 k,k 的值小于或等于链表的长度。
要求:每 k 个节点一组进行翻转,并返回修改后的链表。如果链表节点总数不是 k 的整数倍,则将最后剩余的节点保持原有顺序。
说明:
- 不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
- 假设链表中的节点数目为
n。 - 。
- 。
- 要求设计一个只用
O(1)额外内存空间的算法解决此问题。
示例:
- 示例 1:
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]解题思路
思路 1:迭代
在「0206. 反转链表」中我们可以通过迭代、递归两种方法将整个链表反转。而这道题要求以 k 为单位,对链表的区间进行反转。而区间反转其实就是「0092. 反转链表 II 」这道题的题目要求。
本题中,我们可以以 k 为单位对链表进行切分,然后分别对每个区间部分进行反转。最后再返回头节点即可。
但是需要注意一点,如果需要反转的区间包含了链表的第一个节点,那么我们可以事先创建一个哑节点作为链表初始位置开始遍历,这样就能避免找不到需要反转的链表区间的前一个节点。
这道题的具体解题步骤如下:
- 先使用哑节点
dummy_head构造一个指向head的指针,避免找不到需要反转的链表区间的前一个节点。使用变量index记录当前元素的序号。 - 使用两个指针
cur、tail分别表示链表中待反转区间的首尾节点。初始cur赋值为dummy_head,tail赋值为dummy_head.next,也就是head。 - 将
tail向右移动,每移动一步,就领index加1。- 当
index % k != 0时,直接将tail向右移动,直到移动到当前待反转区间的结尾位置。 - 当
index % k == 0时,说明tail已经移动到了当前待反转区间的结尾位置,此时调用cur = self.reverse(cur, tail.next),将待反转区间进行反转,并返回反转后区间的起始节点赋值给当前反转区间的首节点cur。然后将tail移动到cur的下一个节点。
- 当
- 最后返回新的头节点
dummy_head.next。
关于 def reverse(self, head, tail): 方法这里也说下具体步骤:
head代表当前待反转区间的第一个节点的前一个节点,tail代表当前待反转区间的最后一个节点的后一个节点。- 先用
first保存一下待反转区间的第一个节点(反转之后为区间的尾节点),方便反转之后进行连接。 - 我们使用两个指针
cur和pre进行迭代。pre指向cur前一个节点位置,即pre指向需要反转节点的前一个节点,cur指向需要反转的节点。初始时,pre指向待反转区间的第一个节点的前一个节点head,cur指向待反转区间的第一个节点,即pre.next。 - 当当前节点
cur不等于tail时,将pre和cur的前后指针进行交换,指针更替顺序为:- 使用
next指针保存当前节点cur的后一个节点,即next = cur.next; - 断开当前节点
cur的后一节点链接,将cur的next指针指向前一节点pre,即cur.next = pre; pre向前移动一步,移动到cur位置,即pre = cur;cur向前移动一步,移动到之前next指针保存的位置,即cur = next。
- 使用
- 继续执行第
4步中的1、2、3、4步。 - 最后等到
cur遍历到链表末尾(即cur == tail)时,令「当前待反转区间的第一个节点的前一个节点」指向「反转区间后的头节点」 ,即head.next = pre。令「待反转区间的第一个节点(反转之后为区间的尾节点)」指向「待反转分区间的最后一个节点的后一个节点」,即first.next = tail。 - 最后返回新的头节点
dummy_head.next。
思路 1:代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverse(self, head, tail):
pre = head
cur = pre.next
first = cur
while cur != tail:
next = cur.next
cur.next = pre
pre = cur
cur = next
head.next = pre
first.next = tail
return first
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy_head = ListNode(0)
dummy_head.next = head
cur = dummy_head
tail = dummy_head.next
index = 0
while tail:
index += 1
if index % k == 0:
cur = self.reverse(cur, tail.next)
tail = cur.next
else:
tail = tail.next
return dummy_head.next思路 1:复杂度分析
- 时间复杂度:。其中 为链表的总长度。
- 空间复杂度:。