模拟
- 第一趟遍历,在结点的右侧复制映射。
- 第二趟遍历,复制 r a n d o m random random。
- 第三趟遍历,将链表中的映射结点取出作为新链表。
初始链表如图①。
有必要说明,原结点如
1
1
1~
5
5
5 ,映射结点就是
1
‘
1`
1‘~
5
‘
5`
5‘。
复制映射的结果是,原结点的
n
e
x
t
next
next 指向映射结点,如图②。
有了映射链表后, r a n d o m random random 和 n e x t next next 的关系请看图②, 2 − 4 2-4 2−4 , 2 ‘ − 4 ‘ 2`-4` 2‘−4‘ 的 r a n d o m random random 指向自己理解。(理解了,请看代码)
我们的映射结点经过被映射,复制 r a n d o m random random 这两步后,已经形成结点的深拷贝,现在需要把结点按顺序取出 (看图看代码) 。
至此三次遍历生成随机结点链表的深拷贝。请读者多加思考,复写代码吧~
class Solution {
public:
Node* copyRandomList(Node* head) {
for(auto p = head;p;p=p->next->next) { //在结点右侧复制映射。
auto q = new Node(p->val);
q->next = p->next;
p->next = q;
}
for(auto p = head;p;p=p->next->next) //复制 random
if(p->random) p->next->random = p->random->next;
auto dummy = new Node(-1) , cur = dummy;
for(auto p = head;p;p = p->next){ //断链
cur = cur->next = p->next;
p->next = p->next->next;
}
return dummy->next;
}
};
- 时间复杂度 : O ( n ) O(n) O(n) ,三趟遍历的时间复杂度 O ( n ) O(n) O(n)。
- 空间复杂度 : O ( 1 ) O(1) O(1) ,只使用常数级空间 。