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



这是一个LeetCode问题,我知道它的解决方案,但想知道为什么我的代码不起作用。

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

假设链接列表为1->2->3->4,并且您得到了值为3的第三个节点,则链表应变为1->2->4调用您的功能后

乍一看,我的直觉是像数组一样删除:

将所有节点值移到前面,然后删除尾部,这是我的实现和测试用例:

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)

但删除后,它有两个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

非常感谢您的帮助。

您几乎做到了,但要将所有val值上移一个节点,工作量太大了。您也未能清除最后一个next引用,这就是为什么您看到5打印两次的原因。我将向您展示如何首先正确解决问题,然后解决删除尾部的问题。

您确实可以通过而不是删除节点来解决这个难题,只需将value设置为下一个值,并将next指针指向下一个之后的节点。这就是您需要做的全部,您不需要触摸以下任何节点。您可以有效地删除下一个节点,并使这个节点保留下一个值:

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

成为

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

所以实现很简单:

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

不需要循环。

回到您的尝试,请注意函数中的最后一行没有效果。node是函数中的本地名称,并引用尾部ListNode实例,直到将其设置为None为止。

你有这个:

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

node = None是这样做的:

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

来自上一个节点的传入引用仍然存在

循环完成后,您必须跟踪"onebutlast"节点引用并清除其上的.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

由于您没有对当前节点的引用,因此无法删除它。但您确实有下一个节点的引用。因此,将当前节点的角色赋予下一个节点之前的角色,然后垃圾收集器将删除您的下一个节点,因为您覆盖了node.next.

相关内容

  • 没有找到相关文章

最新更新