簡體   English   中英

Python:如何在O(1)時間內刪除單鏈接列表中的ONLY節點

[英]Python: How to delete ONLY node in a singly-linked list in O(1) time

我已經閱讀了以下帖子,但他們沒有回答我的問題。

發布1

發布2

發布3

這篇文章接近解釋。 @Rishikesh Raje投票最多的回答是,刪除單鏈接列表中的最后一個節點是

[...]通常是不可能的。

為什么通常不可能,而不僅僅是“不可能”? 我的問題既涉及理論本身,又適用於Python? 這個問題是給C的。

此外,我的另一個問題是鏈表只有一個節點的情況,這也使其成為最后一個節點。

背景:我正在LeetCode上解決此問題 盡管它不要求刪除最后一種情況,但我嘗試過,但由於某些我無法查明的功能而似乎無法獲得。 這里的一些方向將不勝感激。 我添加了一種打印值以進行調試的方法。

這是問題:

編寫一個函數以刪除單鏈接列表中的節點(尾部除外),僅授予對該節點的訪問權限。

假設鏈表為1-> 2-> 3-> 4,並且給您第三個節點的值為3,則在調用函數后鏈表應變為1-> 2-> 4。

我的代碼可以達到所需的結果1-> 2-> 4:

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

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

    if nextNode:
      node.val = nextNode.val
      node.next = nextNode.next
    else:
      node = None

  def listToString(self, head):
    string = ""
    while head:
      string += str(head.val) + "\n"
      head = head.next

    return string


head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)

solution = Solution()
print(solution.listToString(head))
print('-'*10)
node = head.next.next
solution.deleteNode(node)
print(solution.listToString(head)) 

運行這個給我:

1
2
3
4

----------
1
2
4

但是當我將底部更改為:

head = ListNode(1)

solution = Solution()
print(solution.listToString(head))
print('-'*10)
node = head
solution.deleteNode(head)
print(solution.listToString(head))

我懂了

1

----------
1

問題是:為什么不打印1而不打印None 請注意,此鏈接列表只有一個節點(這意味着它是最后一個節點),這就是傳遞給函數的內容。 能做到嗎 如果是這樣,我應該做哪些修改?

引用列表的頭節點的函數可以刪除頭之后的任何元素,但是無法刪除頭。

如果您考慮一下,這應該很明顯。 無論您做什么,呼叫者仍然會參考傳入的標頭。

但這本身並不是對鏈表的限制,而僅僅是對API的限制。 使用不同的API,這根本不是不可能的:


引用對擁有頭節點的引用的“列表句柄”對象進行引用的函數可以刪除頭節點,如下所示:

handle.head = handle.head.next

引用頭節點的引用的函數(例如C Node ** )不能直接用Python編寫,但是在可以的語言中,就像使用列表句柄一樣容易:

*head = (*head)->next

列表句柄實際上可以很簡單:

class LinkedList:
    def __init__(self, head=None):
        self.head = head

但是通常您實際上希望將其用於某些用途,例如,向其添加insertdeleteappend等方法,甚至可以存儲長度。 (但是,請注意,這種設計可能會破壞尾部共享,因為兩個不同的列表具有不同的頭部但尾部相同,因為現在您可以通過一個LinkedList句柄更改列表的一部分,而另一個則不知道這樣做了。)


或者,引用頭節點並返回新頭的函數也可以刪除頭:

return head.next

讓我們更詳細地解決這個問題:

def deleteNode(head, node):
    if head == node:
        return None
    ptr = head
    while ptr and ptr.next != node:
        ptr = ptr.next
    if ptr.next == node:
        ptr.next = node.next
    return head

需要一些錯誤處理,但是如果遵循規則,它將起作用:

head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)

# This goes from 1->2->3->4 to 1->2->4
head = deleteNode(head, head.next.next)

# And this goes to 2->4
head = deleteNode(head, head)

而且很顯然,如果將其更改為搜索值而不是節點,則同樣的事情起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM