我正在编写代码来解决以下链表问题:https://leetcode.com/problems/swap-nodes-in-pairs/
总之,就是交换链表中的相邻节点。
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
if not head or not head.next:
return []
prev= head
nex=head
connector= None
output = head.next
count = 0
while prev:
curr = nex.next
if count>=1:
connector.next = curr
nex = curr.next
curr.next = prev
connector = prev
prev=nex
count +=1
return output
如果我运行input [1,2,3,4]
,我会得到一个Error - Found cycle in the ListNode
。然而,当我用这个输入在纸上运行上面的代码时,它就像一个魅力!并在应该的时候退出——没有循环。你知道这种所谓的循环发生在哪里吗?
对于这个问题,您要保持的状态远远超过您需要的状态。例如,count
是完全不必要的。您所需要的不是检查count >= 1
,而是connector is not None
。从一次迭代到下一次迭代,您真正需要的唯一状态是要交换的下一个节点,以及可能的后续节点(作为一种优化,以避免必须多次获取它(。
关于创建循环的特定bug,请考虑循环的第一次迭代。在循环的顶部,nex
等于head
,因此nex
引用列表中的第一个节点。
然后它设置curr = next.next
,因此curr
引用列表中的第二个节点(如果没有第二个结点,则为None
(。然后它设置nex = curr.next
,因此nex
现在引用列表中的第三个节点(如果没有第三个结点,则引用None
(。但是这里有个bug。如果curr
是None
呢?那么curr.next
会导致一个错误,对吧?所以这个问题需要解决。
但假设列表至少有两个节点,此时我们有curr
引用第二个节点,nex
引用第三个节点(如果有(。该列表本身尚未更改。
现在设置curr.next = prev
。由于curr
是第二节点,而prev
仍然是第一节点,因此它将第二节点的后继节点设置为第一节点。它现在创建了一个循环:第一个节点的继任者现在是第二个节点,第二个结点的继任者现在就是第一个节点。第三个节点(如果有的话(不再被列表引用。换句话说,它没有交换前两个节点。它只是在它们之间创造了一个循环。
在这一点上,它几乎偏离了轨道。提示:交换两个节点需要更改三个next
属性:需要将最初引用对中第一个节点的属性更改为引用第二个,需要将对中第一节点的next
属性更改为第二个的next
属性,并且需要改变第二节点的CCD_ 26属性以引用第一节点。之后,第一个节点现在将是第二个节点,第二个点将是第一个节点:
... A -> first -> second -> B ...
变为:
... A -> second -> first -> B ...
所以A.next
需要改变,first.next
需要改变,而second.next
需要改变。B
无需更改。
我建议仔细研究逻辑,看看当有0、1、2、3…时会发生什么。。。列表中的节点。您会立即发现问题,这些问题已经确定,可以解决。
更新:以下是完整的解决方案(仅更改了Solution
(:
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
prev = None
curr = head
while curr and curr.next:
next = curr.next
if prev is None:
head = next
else:
prev.next = next
curr.next = next.next
next.next = curr
prev = curr
curr = curr.next
return head
请注意,循环中的每次迭代都会遍历两个列表节点。循环结束时的两个更新(设置prev
和curr
(使用更新后的curr
节点,该节点现在是当前对中的第二个节点。