題目描述:給出一個鏈表,每個節點包含一個額外增加的隨機指針可以指向鏈表中的任何節點或空的節點。返回一個深拷貝的鏈表。
首先,我先解釋一下題目的意思。就是完全按照給出的鏈表的關係複製鏈表,比如,原鏈表中值爲1的節點的next指向的是值爲2的節點,隨機指針指向值爲3的節點,那麼,複製之後,還是應該滿足這樣的指向關係,但是,因爲是複製的鏈表,所以,存儲在內存空間中的位置當然和原先不同。
我們當然第一想法就是一個個複製節點,但是難度在於什麼呢?複製前面節點的時候並不知道他要指向的節點(不論是隨機還是next)在哪個地址。所以,直接簡單粗暴複製是肯定不行的。
爲了能夠準確複製每個節點的指針,就必須要建立原鏈表與新鏈表對應節點的關係。但是因爲每個節點只有一個next指針,所以,我們還需對新鏈表的next指針做處理,讓節點之前的前後關係保持住。就如下圖所示:
其中,上面的一個是原鏈表,我們發現,只要對兩個鏈表的next指針做出如上圖所示處理,就不難複製隨機指針了。
思路可以這樣:
-
遍歷原鏈表,建立如圖所示的結構
-
根據這個結構,複製隨機指針
-
處理複製鏈表的next指針
代碼如下:
# Definition for singly-linked list with a random pointer.
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# @param head: A RandomListNode
# @return: A RandomListNode
def copyRandomList(self, head):
if head is None:
return head
# 建立關聯結構
cur = head
while cur:
temp = cur
cur = cur.next
copy_node = RandomListNode(temp.label)
copy_node.next = temp.next
temp.next = copy_node
# 複製隨機指針
cur = head
while cur:
temp = cur.random
cur.next.random = cur.random.next if temp else None
cur = cur.next.next
# 複製next指針
copy_cur, copy_head = head.next, head.next
while copy_cur and copy_cur.next:
copy_cur.next = copy_cur.next.next
copy_cur = copy_cur.next
copy_cur.next = None
return copy_head
# write your code here
這個結構的構造很有技巧,充分利用了新舊兩個鏈表節點的next指針,一方面,令原鏈表next指針負責保持節點之間的對應關係,這個邏輯有點“哈希表”的味道;另一方面,由於原鏈表中每個節點都被孤立,所以令新鏈表的next指針負責保持前後關係,不至於讓新生成的節點“找不着”。