LeetCode题目描述:
给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
我的方法:
借鉴之前相邻节点翻转的题目解法,这里也可以采用递归的方法。这里需要考虑两个方面:
- k个节点的链表反转。
- 反转的递归。
- 剩余节点不足k个时的处理。
关于k个节点的链表反转,可以考虑这种思路:可以将整个链表分为两部分l1和l2,其中l1是已经反转的部分,l2是尚未反转的部分。一开始l1为空,而l2是长度为k的链表。
例如:链表1->2->3->4。
- 开始时l1=1,l2=2->3->4。
- l1=2->1, l2=3->4
- 以此类推,直到l2为空,l1完成整个序列的倒排。
虽然做出来的方法不是特别简洁,但总体效果不算太差。执行用时 : 52 ms, 在Reverse Nodes in k-Group的Python提交中击败了96.15% 的用户。内存消耗 : 13.4 MB, 在Reverse Nodes in k-Group的Python提交中击败了38.25% 的用户
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
# 将整个链表分为两段,h1长度为k
h1=head
# p用于记录h1的终点位置
p=None
# 向后移动k个位置
cnt=0
while head and cnt<k:
if cnt==k-1:
p=head
head=head.next
cnt+=1
# 长度超过k时,倒排h1
if p:
p.next=None
t1,tail=self.rev(h1)
t2=self.reverseKGroup(head,k)
tail.next=t2
# 长度未超过k时,h1保持不变
else:
t1=h1
return t1
def rev(self, head):
'''
链表的反转
'''
# 初始化,l1为空,l2为长度k的链表
l1=None
tail=l2=head
# 倒序排序
while l2:
t=l2 #将l2的首个节点赋给中间变量t
l2=l2.next #l2自身移动至下一个节点
t.next=l1 #t的下一个节点设为原来的l1
l1=t #l1更新为t
return l1,tail
一点感悟:
要想很快的解决一个并不熟悉的编程题,应当静下心来。不要着急,很多时候慢慢思考才是最快的解决方式。
别人的方法:
思路上与我的方法似乎没有太大区别。只是在代码的实现上做了精简。我按照自己的理解重写了一遍,具体代码如下。
由于中文网站宕机了,在英文网站上进行的测试:Runtime: 40 ms, faster than 57.71% of Python online submissions for Reverse Nodes in k-Group.Memory Usage: 13.5 MB, less than 5.68% of Python online submissions for Reverse Nodes in k-Group.效果不算太差,但也并不出众。
class Solution(object):
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
# 如果链表长度为0,则返回链表自身
if not head:
return head
# 记录下head,并将链表后移k个节点
cur=head
cnt=0
while cnt<k and cur:
cur=cur.next
cnt+=1
# 对于cur之后的链表,采用递归处理
if cnt==k:
cur=self.reverseKGroup(cur,k)
# head的前k个节点,顺序逐个连接到cur上,实现倒排
while cnt:
tmp=head.next#记录head的下一个节点
head.next=cur#将head与cur相连接,实现倒排
cur=head#增加了一个节点的cur赋回给cur
head=tmp#head指向原来的head.next
cnt-=1
# 这一句是必要的
head=cur
return head