Leetcode中ListNode的Python逻辑

时间:2019-06-09 15:39:44

标签: python linked-list

这是ListNoteLeetCode类的定义:

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

对于代码:

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

注释中的值来自我的猜测。我不明白这个步骤

result_tail = result_tail.next

result_tail = result通过引用传递,因此,当result_tail成为1 -> None时,result也应成为1 -> None。为什么result仍然保留0 -> 1 -> None?当result_tail变成1 -> 2 -> None时,为什么result的尾巴延伸到0 -> 1 -> 2 -> None

result_tail = result_tail.next

类似于

result_tail = result.next.next    

有人可以在这里告诉我逻辑吗?

4 个答案:

答案 0 :(得分:2)

对于那些将来阅读本文的人:我想在本地环境中调试链表问题,所以这就是我所做的。

  1. 通过包含 dunder "repr" 方法修改了 ListNode 的 Leetcode 代码。这是用于当您想打印 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. 接下来,我做了一个递归函数,当你传入一个列表时,它会生成一个嵌套的 ListNode。这样您就可以通过传入列表来测试您的方法(而不必自己手动制作看起来令人困惑的 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. 以下是测试我对“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))

答案 1 :(得分:1)

首先,非常感谢您发布此问题。我研究了相同的问题,看到了这段代码,也感到困惑。然后我听了leetcode的一些评论,来到了这里。

我意识到我的问题是我之前没有纸和笔。我按照循环在纸上画出链表之后,事实证明它很清楚。

如果您仍然不清楚,请尝试按照逻辑绘制链表。不确定我在这里是否使用了正确的术语,但以下是我的理解。

说实话,我认为这与通过参考或传递价值无关。对我来说,这大约是两个变量在开始时被分配了相同的值(内存位置)。将变量视为地址的存储。地址是实际存储位置,是某些值的开始。后来,一个变量(result_tail)不断被重新分配到另一个位置,而一个(结果)保持不变。

Result和result_tail都指向while循环之前的0 | None位置。 0 | None变成0-> 7 | None,然后0-> 7-> 0 | None,最后0-> 7-> 0-> 8 | None每次都由result_tail.next分配。重新分配Result_tail以便在每个循环中更改值,但是结果指向同一位置,即0->...。因此,结果。

答案 2 :(得分:0)

对此的简短回答是,Python是一种通过对象引用的语言,而不是问题中所暗示的通过引用的语言。这意味着:

  1. resultresult_tail是碰巧指向相同值的两个变量
  2. 更改/更改基础值(result_tail.next = ListNode(1))将影响result显示的值
  3. 但是,将变量result_tail分配/指向另一个值不会影响result的值
  4. result_tail = result_tail.next正在分配变量当前分配的节点的下一个节点

以下是分配给变量(r = resultrt = 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

其他参考文献:

答案 3 :(得分:0)

以上所有答案似乎都不错。我只是举个例子供读者理解。

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

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}}]

希望你得到了 CRUX!