题目描述
给你一个长度为 n
的链表,每个节点包含一个额外增加的随机指针 random
,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n
个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next
指针和 random
指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X
和 Y
两个节点,其中 X.random --> Y
。那么在复制链表中对应的两个节点 x
和 y
,同样有 x.random --> y
。
返回复制链表的头节点。
用一个由 n
个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index]
表示:
val
:一个表示 Node.val 的整数。
random_index
:随机指针指向的节点索引(范围从 0
到 n-1
);如果不指向任何节点,则为 null
。
你的代码 只 接受原链表的头节点 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]]
提示:
- 0 <= n <= 1000
- -104 <= Node.val <= 104
- Node.random 为 null 或指向链表中的节点。
代码及注释
/*** Definition for a Node.* type Node struct {* Val int* Next *Node* Random *Node* }*/// copyRandomList 函数用于复制含有随机指针的链表。
func copyRandomList(head *Node) *Node {// 创建一个哈希表,用于存储原链表节点和复制链表节点的对应关系hash := map[*Node]*Node{}// 第一次遍历原链表,创建新节点并存入哈希表for cur := head; cur != nil ; cur = cur.Next {hash[cur] = &Node{cur.Val, nil, nil}}// 第二次遍历原链表,连接复制链表的 Next 和 Random 指针for cur := head; cur != nil; cur = cur.Next {hash[cur].Next = hash[cur.Next]hash[cur].Random = hash[cur.Random]}// 返回复制链表的头节点return hash[head]
}
代码解释
-
创建哈希表:
hash := map[*Node]*Node{}
- 创建一个哈希表
hash
,用于存储原链表节点和复制链表节点的对应关系。
- 创建一个哈希表
-
第一次遍历原链表,创建新节点并存入哈希表:
for cur := head; cur != nil ; cur = cur.Next {hash[cur] = &Node{cur.Val, nil, nil} }
- 使用
for
循环遍历原链表head
。 - 对于每个节点
cur
,创建一个新节点,并将其存入哈希表hash
中。
- 使用
-
第二次遍历原链表,连接复制链表的 Next 和 Random 指针:
for cur := head; cur != nil; cur = cur.Next {hash[cur].Next = hash[cur.Next]hash[cur].Random = hash[cur.Random] }
- 再次使用
for
循环遍历原链表head
。 - 对于每个节点
cur
,从哈希表hash
中获取其对应的复制节点,并连接复制链表的Next
和Random
指针。
- 再次使用
-
返回复制链表的头节点:
return hash[head]
- 返回复制链表的头节点,即哈希表中
head
对应的复制节点。
- 返回复制链表的头节点,即哈希表中
通过使用哈希表,可以在 O(1)
的时间复杂度内找到原链表节点和复制链表节点的对应关系。这样,在第二次遍历原链表时,可以轻松地连接复制链表的 Next
和 Random
指针,从而实现高效地复制含有随机指针的链表。