给定一个链表,每k个节点一组进行组内反转,返回修改后的链表。
其中:
1、k是一个正数,且小于等于列表的长度。
2、如果节点数不是k的整数倍,则最后剩余的节点需要保持原样。
3、只能使用常量的内存。
4、不能改变节点的值,只能修改节点本身。
示例:
输入: 1->2->3->4->5
如果 k = 2, 则输出: 2->1->4->3->5
如果 k = 3, 则输出: 3->2->1->4->5
思路
首先,需要知道组内反转是如何操作的。
给出一个链表,p1 -> p2 -> p3,如果想将整个链表反转,操作如下:
- 在前面添加一个指针,得到 p0 -> p1 -> p2 -> p3
- 开始从头指针开始扫描,每次扫描时,先将当前节点的下一个节点暂存起来,记为 store,然后将当前节点指向上一个节点,然后继续处理 store 这个节点。直至 store 为空。
接下来,便可以先进行分组,再进行组内反转。
分组可以使用递归法来操作:只要剩余链表长度大于等于k,则将前k个进行反转,然后继续递归处理剩下的链表。
python实现
class ListNode:
def __init__(self, x):
if isinstance(x, list):
self.val = x[0]
self.next = None
head = self
for i in range(1, len(x)):
head.next = ListNode(x[i])
head = head.next
else:
self.val = x
self.next = None
def output(self):
'''
输出链表
'''
result = str(self.val)
head = self.next
while(head is not None):
result += f' -> {head.val}'
head = head.next
return '(' + result + ')'
def reverseKGroup(head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
递归,只要剩余链表长度大于等于k,则将前k个进行反转,然后继续处理剩下的链表。
"""
def fun_rec(p):
'''
:type p: ListNode
从链表p的下一位开始,每k个一组进行组内反转。
'''
# 链表长度是否大于等于k
p0 = p
c = 0
while(c < k and p.next):
p = p.next
c += 1
if c < k:
return p
pe = p # 将第k个保存起来
pe2 = pe.next # 将第k+1个保存起来
p1 = p0.next # 将第1个保存起来,作为下一次递归的参数
p0.next = pe # 首指针指向第k个
# 开始循环反转前k个链表
c = 0
p = p1
next = pe2
while(c < k):
p_next = p.next
p.next = next
next = p
p = p_next
c += 1
fun_rec(p1) # 继续处理剩下的链表
if k == 1 or not head:
return head
head0 = ListNode(0)
head0.next = head
fun_rec(head0)
return head0.next
if '__main__' == __name__:
head = ListNode([1,2,3,4,5])
k = 2
print(reverseKGroup(head, k).output())