简体   繁体   English

Python删除链表中的一个节点,只允许访问该节点

[英]Python delete a node in linked list, given just access to that node

This is a LeetCode question, I knew its solution, but wondering about why my code not work. 这是一个LeetCode问题,我知道它的解决方案,但想知道为什么我的代码不起作用。

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. 编写一个函数以删除单链接列表中的节点(尾部除外),仅授予对该节点的访问权限。

Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function 假设链表为1-> 2-> 3-> 4,并且给了第三个节点值为3,则在调用函数后链表应变为1-> 2-> 4

At first glance, my intution is delete like an array: 乍一看,我的直觉是像数组一样删除:

shift all the node values one front, then delete the tail, here's my implementation and test case: 将所有节点值前移一次,然后删除尾部,这是我的实现和测试用例:

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

node1 = ListNode(1)
node2 = ListNode(2)
node3 = ListNode(3)
node4 = ListNode(4)
node5 = ListNode(5)

node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5



def deleteNode(node):
    """
    :type node: ListNode
    :rtype: void Do not return anything, modify node in-place instead.
    """
    while node.next:
        node.val = node.next.val
        node = node.next
    node = None


deleteNode(node4)

But After deletion, it has two 5 value nodes, the tail was still kept, can anyone please explain to me what's wrong here? 但是删除后,它有两个5个值节点,尾部仍然保留,任何人都可以向我解释这是怎么回事?

deleteNode(node4)

node1.val
Out[162]: 1

node1.next.val
Out[163]: 2

node1.next.next.val
Out[164]: 3

node1.next.next.next.val
Out[165]: 5

node1.next.next.next.next.val
Out[166]: 5

Really appreciate any help. 真的感谢任何帮助。

You were almost there, but are doing way too much work shifting all val values up one node. 您几乎在那里,但是正在做太多工作,将所有 val值上移一个节点。 You also failed to clear the last next reference, which is why you see 5 printed twice . 您也没有清除上一个next参考,这就是为什么您看到5打印两次的原因 I'll show you how to solve the problem properly first, then address removing the tail. 我将向您展示如何正确解决该问题,然后解决尾巴问题。

You can indeed solve this puzzle by not deleting the node, just by setting the value to the next value, and the next pointer to the node after the next. 您确实可以解决此难题,方法是删除节点,而只需将value设置为下一个值,并将next指针指向下一个节点即可。 And that is all you need to do, you don't need to touch any of the following nodes. 这是所有你需要做的,你不需要接触任何以下节点。 You'd effectively delete the next node and making this node hold the next value instead: 您将有效地删除下一个节点,并使节点保留下一个值:

      node
       |
       v
      ---------        ---------       
---> | val: va | ---> | val: vb | ---> ?
      ---------        ---------     

becomes 变成

      node
       |
       v
      ---------        ---------       
---> | val: vb | -+   | val: vb |   -> ?
      ---------   |    ---------   |   
                  |                |
                   ----------------

So the implementation is as simple as: 因此实现很简单:

def deleteNode(node):
    """
    :type node: ListNode
    :rtype: void Do not return anything, modify node in-place instead.
    """
    node.val = node.next.val
    node.next = node.next.next

No loop required. 无需循环。

Back to your attempt, note that the last line in your function has no effect. 回到您的尝试,请注意函数的最后一行无效。 node is a local name in your function, and references the tail ListNode instance, until you set it to None instead. node是函数中的本地名称 ,并引用尾部ListNode实例, 直到将其设置为None 为止

You had this: 你有这个:

      node
       |
       v
      -----------       
---> | val: tail | ---> None 
      ----------- 

and node = None does this: 并且node = None这样做:

      node -> None
       X
       |
       v
      -----------       
---> | val: tail | ---> None 
      ----------- 

That incoming reference from the previous node is still there . 从上一个节点传入的引用仍然存在

You'd have to track the 'one-but-last' node reference and clear the .next attribute on that once looping is done: 循环完成后,您必须跟踪“最后一个”节点引用并清除.next属性:

while node.next:
    node.val = node.next.val
    prev, node = node, node.next

# clear reference to tail
prev.next = None
def deleteNode(node):
   node.val = node.next.val
   node.next = node.next.next

Since you don't have a reference to your current node, you can't delete it. 由于您没有对当前节点的引用,因此无法删除它。 But you do have a ref to your next node. 但是您确实有对下一个节点的引用。 So give your current node the role that your next node previously had, and then the garbage collector will delete your next node, since there are no refs to it left because you overwrote node.next. 因此,为当前节点赋予下一个节点以前的角色,然后垃圾收集器将删除下一个节点,因为由于重写了node.next,因此没有剩余引用。

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

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