题目如下:
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
思路: 利用ES6中的map数据结构。map数据结构的键可以是各种数据类型。因此在我们构建的map中,map的key为每一个节点,map的value为new出来的新node,这个新node的value值可以立即添加,但next值和random值先不设置,因为random值可能还没有遍历到。全部遍历一遍之后再从头添加每个新node的next值和random值。
代码如下:
/**
* // 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) {
if(!head) return head;
let node = head;
let map = new Map();
while(node){
map.set(node,new Node(node.val));
node = node.next;
};
node = head;
while(node){
map.get(node).next = map.get(node.next) || null;
map.get(node).random = map.get(node.random);
node = node.next;
};
return map.get(head);
};
通过了测试用例。
好的解法:
- 复制各节点,并构建拼接链表(当前节点指向当前节点的复制节点,复制节点指向当前节点的next节点)。
- 构建各新节点的 random 指向。
- 将一个链表拆分成两个链表。
代码如下:
/**
* @param {Node} head
* @return {Node}
*/
var copyRandomList = function (head) {
if (head == null) return null;
// cur指向头节点
let cur = head;
// 复制各节点,并构建拼接链表
while (cur) {
// 复制cur节点并且next正确指向之后 再延着next指针走下去
let temp = new Node(cur.val);
temp.next = cur.next;
cur.next = temp;
cur = temp.next;
}
cur = head;
// 构建各新节点的 random 指向
while (cur) {
if (cur.random) cur.next.random = cur.random.next;
cur = cur.next.next;
}
// 拆分两链表;
cur = head.next;
let pre = head,
res = head.next;
while (cur.next) {
pre.next = pre.next.next;
cur.next = cur.next.next;
pre = pre.next;
cur = cur.next;
}
// 单独处理原链表尾节点
pre.next = null;
// 返回新链表头节点
return res;
};