开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
复制带随机指针的链表
给你一个长度为 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 <= 104Node.random为null或指向链表中的节点。
解题思路:
- 先遍历 head,获取所有节点,放入 mapNodeList中(key为节点,value为位置)。用于后续查找随机节点的位置。
- 重置 cur 和 count。
- 重新遍历 head。
- 查找arr中有没有已经插入的随机节点(下边 3.3 步骤,可能会插入随机节点),没有则创建新节点newNextNode,并缓存到 arr 中。
- 如果原节点cur有random,则查找原链表当前节点 cur 的 random 指向的位置randomIndex(利用nodeList直接可以get到当前cur.random的位置)。
- 根据randomIndex从arr中查找对应项,如果不存在则创建新的randomNode,赋值给 newNextNode.random,并将其缓存到 arr 中。
我的答案:
/**
* // Definition for a Node.
* function Node(val, next, random) {
* this.val = val;
* this.next = next;
* this.random = random;
* };
*/
/**
* @param {Node} head
* @return {Node}
*/
var copyRandomList = function(head) {
let newHead = new Node(),
cur = head,
p = newHead,
count = 0,
mapNodeList = new Map()
arr = []
while (cur) {
mapNodeList.set(cur, count)
count++
cur = cur.next
}
count = 0
cur = head
while (cur) {
let random = cur.random,
newNextNode = arr[count] ? arr[count] : new Node(cur.val)
arr[count] = newNextNode
if (random !== null) {
let randomIndex = mapNodeList.get(random),
newRandom = arr[randomIndex] ? arr[randomIndex] : new Node(random.val)
newNextNode.random = newRandom
arr[randomIndex] = newRandom
}
p.next = newNextNode
p = p.next
cur = cur.next
count++
}
return newHead.next
};
最后
如果有更好的解法或者思路, 欢迎在评论区和我交流~ ღ( ´・ᴗ・` )