简体   繁体   English

Leetcode中ListNode的Python逻辑

[英]Python Logic of ListNode in Leetcode

Here is the definition of ListNote class in LeetCode :这里的定义ListNoteLeetCode

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

For the code:对于代码:

result = ListNode(0)
#result = 0 -> None
result_tail = result
#result_tail = 0 -> None
result_tail.next = ListNode(1)
#result_tail = 0 -> 1 -> None
#result = 0 -> 1 -> None
result_tail = result_tail.next
#result_tail = 1 -> None
#result = 0 -> 1 -> None
result_tail.next = ListNode(2)
#result_tail = 1 -> 2 -> None
#result = 0 -> 1 -> 2 -> None
result_tail = result_tail.next
#result_tail = 2 -> None
#result = 0 -> 1 -> 2 -> None

The values in comments are from my guessing.评论中的值来自我的猜测。 I cannot understand the step我无法理解这一步

result_tail = result_tail.next

result_tail = result is pass by reference, so when result_tail becomes 1 -> None , result should also become 1 -> None . result_tail = result是通过引用传递的,所以当result_tail变成1 -> Noneresult也应该变成1 -> None Why does result still keep 0 -> 1 -> None ?为什么result仍然保持0 -> 1 -> None And when result_tail becomes 1 -> 2 -> None , why does result extend its tail to 0 -> 1 -> 2 -> None ?result_tail变为1 -> 2 -> None ,为什么result将其尾部扩展到0 -> 1 -> 2 -> None

result_tail = result_tail.next

is something like就像

result_tail = result.next.next    

Can anyone tell me the logic here?谁能告诉我这里的逻辑?

The short answer to this is that, Python is a pass-by-object-reference language, not pass-by-reference as implied in the question.对此的简短回答是,Python 是一种传递对象引用语言,而不是问题中暗示的传递引用。 It means that:这意味着:

  1. result and result_tail are two variables that happen to point at the same value resultresult_tail是两个恰好指向同一个值的变量
  2. Mutation / Changing of the underlying value ( result_tail.next = ListNode(1) ) will affect the value shown by result底层值( result_tail.next = ListNode(1) )的变异/更改将影响result显示的值
  3. However, assigning / pointing the variable result_tail to another value will NOT affect the value of result但是,将变量result_tail分配/指向另一个值不会影响result的值
  4. result_tail = result_tail.next is assigning the next node of the node that is currently assigned by the variable result_tail = result_tail.next是赋值当前变量赋值的节点的下一个节点

The following is an visualization of the values that are assigned to the variables ( r = result , rt = result_tail ):以下是分配给变量的值的可视化( r = result , rt = result_tail ):

result = ListNode(0)
#r
#0 -> None

result_tail = result
#r
#0 -> None
#rt

result_tail.next = ListNode(1)
#r
#0 -> 1 -> None
#rt

result_tail = result_tail.next
#r
#0 -> 1 -> None
#     rt

result_tail.next = ListNode(2)
#r
#0 -> 1 -> 2 -> None
#     rt

result_tail = result_tail.next
#r
#0 -> 1 -> 2 -> None
#          rt

References for additional reading:补充阅读参考:

First, thank you so much for posting this question.首先,非常感谢您发布这个问题。 I worked on the same problem and saw this piece of code and was puzzled too.我解决了同样的问题,看到了这段代码,也很困惑。 Then I followed some comments from leetcode and came here.然后我跟着 leetcode 的一些评论来到了这里。

I realize that my problem was that I didn't have a pen and paper earlier.我意识到我的问题是我之前没有笔和纸。 After I drew the linked list on the paper by following the loop, it turned out to be quite clear.我按照循环在纸上画了链表后,结果就很清楚了。

If you are still not clear about this, please try to draw the linked list by following the logic.如果您对此还不是很清楚,请尝试按照逻辑绘制链表。 Not sure if I got the right term here but below is my understanding.不确定我是否在这里得到了正确的术语,但以下是我的理解。

To be honest, I do not think this is related to pass by reference or value.老实说,我不认为这与通过引用或值传递有关。 To me, this is just about two variables being assigned with the same value(memory location) at the beginning.对我来说,这只是在开始时为两个变量分配了相同的值(内存位置)。 Think of variables as storage of address.将变量视为地址的存储。 Address is the real memory location which is the start of some value.地址是实际内存位置,它是某个值的开始。 Later on, one variable(result_tail) kept getting reassigned to a different location and one(result) stays the same.后来,一个变量(result_tail)不断被重新分配到不同的位置,而 one(result)保持不变。

Result and result_tail both point to the location of 0|None before the while loop. Result 和 result_tail 都指向 while 循环前的 0|None 位置。
0|None grew into 0->7|None , then 0->7->0|None and at last 0->7->0->8|None by result_tail.next being assigned every time. 0|None变成0->7|None ,然后是0->7->0|None ,最后是0->7->0->8|None通过 result_tail.next 每次都被分配。 Result_tail gets reassigned so value changed during each loop, but result points to the same location which is the 0->.... Thus the result. Result_tail 被重新分配,因此在每个循环期间值都会改变,但结果指向相同的位置,即0->....因此结果。

For those reading this in the future: I wanted to debug linked list problems on a local environment so here is what I did.对于那些将来阅读本文的人:我想在本地环境中调试链表问题,所以这就是我所做的。

  1. Modified the Leetcode code for ListNode by including the dunder " repr " method.修改了 ListNode 的 Leetcode 代码,加入了 dunder“ repr ”方法。 This is for when you want to print a ListNode to see what its value and next node(s).这是用于当您想要打印 ListNode 以查看其值和下一个节点时。
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

    def __repr__(self):
        return "ListNode(val=" + str(self.val) + ", next={" + str(self.next) + "})"
  1. Next, I made a recursive function that makes a nested ListNode when you pass in a list.接下来,我做了一个递归函数,当你传入一个列表时,它会生成一个嵌套的 ListNode。 This is so you can test your methods by passing in lists (instead of having to manually make a confusing looking ListNode yourself.这样你就可以通过传入列表来测试你的方法(而不必自己手动制作一个看起来很混乱的 ListNode。
def list_to_LL(arr):
    if len(arr) < 1:
        return None

    if len(arr) == 1:
        return ListNode(arr[0])
    return ListNode(arr[0], next=list_to_LL(arr[1:]))
  1. Here is an example that tests my answer for the "reverseList" problem:这是一个测试我对“reverseList”问题的回答的示例:
def reverseList(head: ListNode) -> ListNode:
    prev = None
    while head:
        next_node = head.next
        head.next = prev
        prev = head
        head = next_node

    return prev


# test cases
t1 = list_to_LL([1, 2, 3, 4, 5])  #ListNode(val=1, next={ListNode(val=2, next={ListNode(val=3, next={ListNode(val=4, next={ListNode(val=5, next={None})})})})})
t2 = list_to_LL([1, 2])  #ListNode(val=1, next={ListNode(val=2, next={None})})
t3 = list_to_LL([])

# answers
print(reverseList(t1))
print(reverseList(t2))
print(reverseList(t3))

All above answers seems good.以上所有答案似乎都很好。 I am just adding up an example for the reader's understanding.我只是举个例子供读者理解。

Input given : [[1,4,5],[1,3,4],[2,6]]给定输入: [[1,4,5],[1,3,4],[2,6]]

ListNode object description: ListNode 对象说明:

[ListNode{val: 1, next: ListNode{val: 4, next: ListNode{val: 5, next: None}}}, ListNode{val: 1, next: ListNode{val: 3, next: ListNode{val: 4, next: None}}}, ListNode{val: 2, next: ListNode{val: 6, next: None}}]

Hope you got the CRUX!希望你得到了 CRUX!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM