在Python中“就地”修改链接列表节点

时间:2019-07-07 00:11:51

标签: python linked-list singly-linked-list

我在练习一个(非常简单的)LeetCode问题时遇到了我的问题。但是,我真正的问题是关于Python的问题,而不是问题本身的答案。您将在下面看到完整的问题说明,在此之后我将解释我的方法,将其与实际解决方案进行对比,然后(最后)提出我的问题。


LeetCode问题:Delete Node in Linked List

问题:

编写一个函数以删除单链接列表中的节点(尾部除外),只允许访问该节点。

给出链表-head = [4,5,1,9],如下所示:

img

示例1:

Input: head = [4,5,1,9], node = 5
Output: [4,1,9]
Explanation: You are given the second node with value 5, the linked list should become 4 -> 1 -> 9 after calling your function.

示例2:

Input: head = [4,5,1,9], node = 1
Output: [4,5,9]
Explanation: You are given the third node with value 1, the linked list should become 4 -> 5 -> 9 after calling your function.

注意:

  • 链接列表将至少包含两个元素。
  • 所有节点的值都是唯一的。
  • 给定的节点将不会是尾部,并且将始终是链表的有效节点。
  • 请勿从函数中返回任何内容。

我的方法:

我提出了一个快速答案(这在O(n)处是次优的,但这不是重点),我将被删除的节点和所有节点的值都向左移动一个单位来重新分配它们的值。 。在此示例中,接下来将重新分配带括号的节点:

  1. 4->[5]->1->9->None成为
  2. 4->1->[1]->9->None,然后
  3. 4->1->9->[9]->None,最后
  4. 4->1->9->None

或者至少是我从下面编写的代码中得到的期望。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteNode(self, node):
        while node != None:
            node = node.next

令我惊讶的是,输入链接列表与输出链接列表完全相同。这是输出的屏幕截图:

LeetCode Output for incorrect deleteNode function


实际解决方案:

solution的复杂度为O(1),下面显示了相应的(正确的)输出。

class Solution:
    def deleteNode(self, node):
        node.val = node.next.val
        node.next = node.next.next

LeetCode Output for correct deleteNode function


我的问题:

为什么node.val = node.next.valnode.next = node.next.next修改“就地”链表的节点,而在node中重新分配node = node.next对对象{ {1}}个参考?

1 个答案:

答案 0 :(得分:4)

node = node.next只是重新分配了deleteNode的参数,而不会影响该函数之外的任何内容。

这样想:您希望它修改x吗?

x = 1

def f(a):
    a = 2

f(x)

不会。 a只是f内部的本地参考。重新分配它所做的只是更改对象a指向的对象。

将其与以下内容进行比较:

x = []

def f(a):
    a.append(2)

f(x)

这将更改x。在这里,您不是在重新分配本地参考,而是在变异本地参考指向的对象。使用第二个代码,node.val = node.next.val更改node内的字段。它将更改对象。

这就是您的两段代码之间的区别。第一部分代码只是更改了对该对象的引用。第二段代码更改了对象本身。