138. Copy List with Random Pointer
題目
題目大意
解題思路
對於數據結構複製,甭管他怎麼變,你就記住最簡單的方式:一個哈希表 + 兩次遍歷
- 第一次遍歷專門clone節點,藉助 Hash表把原始節點和clone節點的映射存儲起來;
- 第二次專門組裝節點,照著原數據結構的樣子,把clone節點的指標組裝起來。
Big O
- 時間複雜 :
O(n)
,其中 n 是鏈表的長度。 對於每個節點,我們至多訪問其「後繼節點」和「隨機指標指向的節點」各一次,均攤每個點至多被訪問兩次。 - 空間複雜 :
O(n)
其中 n 是鏈表的長度。 為哈希表的空間開銷
來源
- https://leetcode.com/problems/copy-list-with-random-pointer/description/
- https://leetcode.cn/problems/
解答
package copylistwithrandompointer
/**
* Definition for a Node.
* type Node struct {
* Val int
* Next *Node
* Random *Node
* }
*/
var cacheMap map[*Node]*Node
// 時間複雜 O(n), 空間複雜 O(n)
func copyRandomList(head *Node) *Node {
cacheMap = make(map[*Node]*Node)
return deepCopy(head)
}
func deepCopy(node *Node) *Node {
if node == nil {
return nil
}
if n, ok := cacheMap[node]; ok {
return n
}
newNode := &Node{Val: node.Val}
cacheMap[node] = newNode
newNode.Next = deepCopy(node.Next)
newNode.Random = deepCopy(node.Random)
return newNode
}
func copyRandomList2(head *Node) *Node {
cMap := make(map[*Node]*Node)
cur := head
// 第一次遍歷專門clone節點,藉助 Hash表把原始節點和clone節點的映射存儲起來;
for cur != nil {
newNode := &Node{Val: cur.Val}
cMap[cur] = newNode
cur = cur.Next
}
// 第二次專門組裝節點,照著原數據結構的樣子,把clone節點的指標組裝起來。
newHead := cMap[head]
for head != nil {
node := cMap[head]
node.Next = cMap[head.Next]
node.Random = cMap[head.Random]
head = head.Next
}
return newHead
}
Benchmark