题目
请实现函数 ComplexListNOde,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。节点定义如下:
/**
* // Definition for a Node.
* function Node(val, next, random) {
* this.val = val;
* this.next = next;
* this.random = random;
* };
*/
示例1
7 --> 13 --> 11 --> 10 --> 1 --> null
| ^___| | ^_____| ^ | ^
| | |____________| | |
| |_________________________|
|_________________________________|
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
提示:
- -10000 <= Node.val <= 10000
- Node.random 为空(null)或指向链表中的节点。
- 节点数目不超过 1000 。
题解
回溯 + 哈希表
/**
* // 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, cachedNode = new Map()) {
if (head === null) {
return null;
}
if (!cachedNode.has(head)) {
cachedNode.set(head, { val: head.val });
Object.assign(cachedNode.get(head), {
next: copyRandomList(head.next, cachedNode),
random: copyRandomList(head.random, cachedNode)
});
}
return cachedNode.get(head);
};
复杂度分析
- 时间复杂度:O(n),其中 n 是链表的长度。对于每个节点,我们至多访问其「后继节点」和「随机指针指向的节点」各一次,均摊每个点至多被访问两次。
- 空间复杂度:O(n),其中 n 是链表的长度。为哈希表的空间开销。
迭代 + 节点拆分
/**
* // 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, cachedNode = new Map()) {
if (head === null) {
return null;
}
for (let node = head; node !== null; node = node.next.next) {
const nodeNew = new Node(node.val, node.next, null);
node.next = nodeNew;
}
for (let node = head; node !== null; node = node.next.next) {
const nodeNew = node.next;
nodeNew.random = (node.random !== null) ? node.random.next : null;
}
const headNew = head.next;
for (let node = head; node !== null; node = node.next) {
const nodeNew = node.next;
node.next = node.next.next;
nodeNew.next = (nodeNew.next !== null) ? nodeNew.next.next : null;
}
return headNew;
};
复杂度分析
- 时间复杂度:O(n),其中 n 是链表的长度。我们只需要遍历该链表三次。
- 空间复杂度:O(1)。注意返回值不计入空间复杂度。
引用
- 剑指offer书籍
- 力扣题解