138. [链表][哈希表][回溯]复制带随机指针的链表
138. 复制带随机指针的链表
方法一:两次哈希表
- 第一次,用哈希表存放各个节点的值(以创建新节点的方式复制);
- 第二次,复制各个节点的指向;
class Solution {
public Node copyRandomList(Node head) {
HashMap<Node, Node> hashMap = new HashMap<Node, Node>(); // 创建HashMap集合
Node curr = head;
// 复制节点值
while (curr != null){
// 存储
hashMap.put(curr, new Node(curr.val)); // 顺序遍历,存储老节点和新节点(先存储新创建的结点值)
curr = curr.next;
}
// 复制节点指向
curr = head;
while (curr != null){
hashMap.get(curr).next = hashMap.get(curr.next);
hashMap.get(curr).random = hashMap.get(curr.random);
curr = curr.next;
}
return hashMap.get(head);
}
}
方法二:\(O(1)空间的迭代复制\)


如上图的直观解释,我们可以直接将复制节点创建在源结点的右侧,并让源结点的next指针指向它,方便我们下一步复制random节点。
所有节点都复制好以后,我们再将链表解开。
// 执行耗时:0 ms,击败了100.00% 的Java用户
// 内存消耗:37.6 MB,击败了100.00% 的Java用户
class Solution {
public Node copyRandomList(Node head) {
if (head == null){
return null;
}
Node ptr = head;
while (ptr != null){
// A 复制 A'(复制节点的值)
Node newNode = new Node(ptr.val);
// 然后复制的A'放置在A的旁边
// src: A->B->C
// after copy: A->A'->B->B'->C->C'
newNode.next = ptr.next;
ptr.next = newNode;
ptr = newNode.next;
}
// 此时,我们仅仅完成了next指针的复制
// 下面我们需要复制random指针
// A->A'->B->B'->C->C'
ptr = head;
while (ptr != null){
ptr.next.random = (ptr.random != null) ? ptr.random.next : null; // 因为正好复制在了下一个节点里
ptr = ptr.next.next;
}
// 将原链表与克隆链表分开
Node ptr_old = head;
Node ptr_new = head.next;
Node head_old = head.next;
while (ptr_old != null){
ptr_old.next = ptr_old.next.next;
ptr_new.next = (ptr_new.next != null) ? ptr_new.next.next : null;
ptr_old = ptr_old.next;
ptr_new = ptr_new.next;
}
return head_old;
}
}

浙公网安备 33010602011771号