给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解题思路
关于这个问题,首先我们很容易想到的思路就是通过两个指针指向一个group
的头和尾,然后对这个group
做reverse
操作,如果这两个指针间的距离小于k
,我们不进行操作。另外,我们要确定我们reverse
的边界,我这里假设边界为(pre, lat)
pre lat
h -> 1 -> 2 -> 3 -> 4 -> 5
k = 3
另外,大家也可以想一想,我们的边界能不能是[pre, lat]
、(pre, lat]
、[pre, lat)
这样的呢?这里的[pre, lat]
实际上就是Leetcode 206:反转链表(最详细解决方案!!!)文章的内容,和这个问题相比,我们这里有一个不变量pre
。
接着,我们来看怎么进行reverse
,首先定义两个指针lpre=pre.next
和cur=lpre.next
pre lpre cur lat
h -> 1 -> 2 -> 3 -> 4 -> 5
k = 3
当cur!=lat
的时候我们要做的操作就是lpre.next=cur.next
、cur.next=pre.next
、pre.next=cur
、cur=lpre.next
pre lpre cur lat
-----------
| |
h 1 <- 2 3 -> 4 -> 5
| |
-----------
我们就可以很容易的写出这个reverse
操作,我们函数_reverseGroup
的返回值是lat
的前一个node
def _reverseGroup(self, pre, lat):
lpre = pre.next
cur = lpre.next
while cur != lat:
lpre.next = cur.next
cur.next = pre.next
pre.next = cur
cur = lpre.next
return lpre
接着我们就要写整个大循环。整个大循环结束的条件是cur!=None
,然后每k
个节点我们做一次reverse
,将reverse
的结果给pre
,接着更新cur=pre.next
。如果没有k
个节点的话,我们cur=cur.next
即可。
while cur != None:
if t % k == 0:
pre = self._reverseGroup(pre, cur.next)
cur = pre.next
else:
cur = cur.next
以下是整个代码
class Solution:
def _reverseGroup(self, pre, lat):
lpre = pre.next
cur = lpre.next
while cur != lat:
lpre.next = cur.next
cur.next = pre.next
pre.next = cur
cur = lpre.next
return lpre
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
h = ListNode(-1)
h.next = head
pre = h
cur = head
t = 1
while cur != None:
if t % k == 0:
pre = self._reverseGroup(pre, cur.next)
cur = pre.next
else:
cur = cur.next
t += 1
return h.next
我们当然可以把这个写到一个函数中。我们有两种做法
- 先遍历一遍链表,统计链表长度,然后每
k
个链表做反转操作。 - 遍历链表的过程中,每
k
个链表做反转操作
class Solution:
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
h = ListNode(-1)
h.next = head
pre = h
cur = head
while cur != None:
t = cur
count = 1
while count < k and t != None:
t = t.next
count += 1
if count == k and t != None:
for _ in range(k - 1):
lat = cur.next
cur.next = lat.next
lat.next = pre.next
pre.next = lat
pre = cur
cur = pre.next
else:
break
return h.next
对于第二种
class Solution:
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
h = ListNode(-1)
h.next = head
pre = h
cur = head
while cur != None:
t = cur
count = 1
while count < k and t != None:
t = t.next
count += 1
if count == k and t != None:
for _ in range(k - 1):
lat = cur.next
cur.next = lat.next
lat.next = pre.next
pre.next = lat
pre = cur
cur = pre.next
else:
break
return h.next
我更喜欢第一种写法。
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!