问题描述
我正在处理链表中k个节点的问题反转组。当我编写分配操作以进行冲销时,我给出了:
cur,cur.next,prev = cur.next,prev,cur
其中cur
和prev
表示当前节点和先前节点。发生的最有趣的事情是,当我给:
cur.next,cur,prev = prev,cur
这是可以接受的,而前者却给了我超过时间的限制。
我相信在Python中,将多个变量分配为元组,并且仅考虑所有变量的先前值。那么两个陈述应该是完全相同的权利吗?还是我错了?请在这里帮助我。
这是一个leetcode问题,我提供了整个代码以防万一。该行标有3 *,如果我单独更改该行,代码将从接受的跃跃到超过时间限制。
h=jump=ListNode(0)
h.next=left=right=head
while True:
i=0
while i<k and right:
i+=1
right=right.next
if i==k:
prev=right
cur=left
for _ in range(k):
***cur.next,cur***
jump.next,jump,left=prev,left,right
else:
return h.next
上面的代码被接受。仅当我更改线路时,它才陷入一个循环,超过了时间限制。
解决方法
分配是from left to right,所以...
cur,cur.next,... = ...
以上内容首先分配给cur
。然后转到cur.next
,其中cur
已已经是新值。
cur.next,cur,... = ...
这首先分配给cur.next
,其中cur
仍然是旧值。然后转到cur
。
所以您与众不同。您更改了不同节点的.next
。
很好的问题!
现在我也明白了这个问题! (ˆ_ˆ)
这是链接列表中非常普遍的问题,在遍历链接列表或执行任何其他操作时,我们应始终注意语句更改的顺序。
事实是,如果我们的陈述中的某些必需命令丢失了(在这种情况下),最终将发生以下两种情况之一:
- 如果您愿意的话,任何一个节点都将丢失与下一个节点的链接,并且该节点将变为无链接;
- 或者一个节点将链接回其自身(如圆形),并且列表将变得过时;
您的代码正确无误即可正常工作,而没有超过时间限制(经过测试):
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self,val=0,next=None):
# self.val = val
# self.next = next
class Solution(object):
def reverseKGroup(self,head,k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
h = jump = ListNode(0)
h.next = left = right = head
while True:
i = 0
while i < k and right:
i += 1
right = right.next
if i == k:
prev = right
cur = left
for _ in range(k):
cur.next,prev = prev,cur
jump.next,jump,left = prev,left,right
else:
return h.next
我们还可以使用辅助功能。会在没有超过时间限制(TLE)的情况下通过:
class Solution:
def reverseKGroup(self,k):
def rev(head,count):
prev,curr,next = None,head
while count > 0:
next = curr.next
curr.next = prev
prev,count = curr,next,count - 1
return (curr,prev)
count,curr = 0,head
while curr and count < k:
curr,count = curr.next,count + 1
if count < k:
return head
new_head,prev = rev(head,count)
head.next = self.reverseKGroup(new_head,k)
return prev
这里是LeetCode的官方解决方案,带有解释性注释:
递归
class Solution:
def reverseLinkedList(self,k):
# Reverse k nodes of the given linked list.
# This function assumes that the list contains
# atleast k nodes.
new_head,ptr = None,head
while k:
# Keep track of the next node to process in the
# original list
next_node = ptr.next
# Insert the node pointed to by "ptr"
# at the beginning of the reversed list
ptr.next = new_head
new_head = ptr
# Move on to the next node
ptr = next_node
# Decrement the count of nodes to be reversed by 1
k -= 1
# Return the head of the reversed list
return new_head
def reverseKGroup(self,head: ListNode,k: int) -> ListNode:
count = 0
ptr = head
# First,see if there are atleast k nodes
# left in the linked list.
while count < k and ptr:
ptr = ptr.next
count += 1
# If we have k nodes,then we reverse them
if count == k:
# Reverse the first k nodes of the list and
# get the reversed list's head.
reversedHead = self.reverseLinkedList(head,k)
# Now recurse on the remaining linked list. Since
# our recursion returns the head of the overall processed
# list,we use that and the "original" head of the "k" nodes
# to re-wire the connections.
head.next = self.reverseKGroup(ptr,k)
return reversedHead
return head
迭代
class Solution:
def reverseLinkedList(self,k: int) -> ListNode:
ptr = head
ktail = None
# Head of the final,moified linked list
new_head = None
# Keep going until there are nodes in the list
while ptr:
count = 0
# Start counting nodes from the head
ptr = head
# Find the head of the next k nodes
while count < k and ptr:
ptr = ptr.next
count += 1
# If we counted k nodes,reverse them
if count == k:
# Reverse k nodes and get the new head
revHead = self.reverseLinkedList(head,k)
# new_head is the head of the final linked list
if not new_head:
new_head = revHead
# ktail is the tail of the previous block of
# reversed k nodes
if ktail:
ktail.next = revHead
ktail = head
head = ptr
# attach the final,possibly un-reversed portion
if ktail:
ktail.next = head
return new_head if new_head else head
参考文献
- 有关其他详细信息,请参见Discussion Board,在这里您可以找到许多具有各种languages且已被广泛接受的解决方案,包括低复杂度算法和渐近runtime / {{ 3}}分析memory,1 。