# LeetCode如何實現復制帶隨機指針的鏈表
## 問題描述
LeetCode第138題"復制帶隨機指針的鏈表"(Copy List with Random Pointer)要求我們深度復制一個特殊的鏈表結構。這種鏈表的每個節點除了包含標準的`val`和`next`指針外,還包含一個可能指向鏈表中任意節點或為`null`的`random`指針。
```python
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
普通鏈表的復制非常簡單,只需遍歷原鏈表逐個創建新節點即可。但帶隨機指針的鏈表存在以下難點:
def copyRandomList(head: 'Node') -> 'Node':
if not head:
return None
# 建立原節點到新節點的映射
mapping = {}
curr = head
while curr:
mapping[curr] = Node(curr.val)
curr = curr.next
# 設置新節點的next和random指針
curr = head
while curr:
if curr.next:
mapping[curr].next = mapping[curr.next]
if curr.random:
mapping[curr].random = mapping[curr.random]
curr = curr.next
return mapping[head]
原鏈表:A -> B -> C
穿插后:A -> A' -> B -> B' -> C -> C'
def copyRandomList(head: 'Node') -> 'Node':
if not head:
return None
# 1. 在每個原節點后插入新節點
curr = head
while curr:
new_node = Node(curr.val)
new_node.next = curr.next
curr.next = new_node
curr = new_node.next
# 2. 設置新節點的random指針
curr = head
while curr:
if curr.random:
curr.next.random = curr.random.next
curr = curr.next.next
# 3. 分離兩個鏈表
curr = head
new_head = head.next
while curr:
temp = curr.next
curr.next = temp.next
if temp.next:
temp.next = temp.next.next
curr = curr.next
return new_head
在實際編碼中需要考慮以下邊界情況:
# 示例1
# 輸入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
# 輸出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
# 示例2
# 輸入:head = [[1,1],[2,1]]
# 輸出:[[1,1],[2,1]]
# 示例3
# 輸入:head = [[3,null],[3,0],[3,null]]
# 輸出:[[3,null],[3,0],[3,null]]
| 方法 | 時間復雜度 | 空間復雜度 | 優點 | 缺點 |
|---|---|---|---|---|
| 哈希表映射法 | O(N) | O(N) | 思路直觀,兩次遍歷 | 需要額外哈希表空間 |
| 節點穿插法 | O(N) | O(1) | 常數空間,適合空間限制 | 需要三次遍歷,修改原鏈表 |
如何處理循環引用的random指針?
為什么穿插法不需要額外空間?
如果鏈表很大,哪種方法更優?
復制帶隨機指針的鏈表是考察對鏈表結構和哈希表應用的經典題目。兩種主要解法各有優劣:
掌握這道題有助于理解更復雜的鏈表操作和對象引用關系,是數據結構學習中的重要里程碑。 “`
這篇文章共計約1700字,涵蓋了問題描述、解決方案、復雜度分析、邊界情況、測試用例、方法比較和擴展思考等內容,采用Markdown格式編寫,可直接用于技術博客或面試準備。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。