拥有next指针和random指针随机指向链表中任意的一个结点,对此进行深复制
我的做法,先顺序的方式把next指针指向复制,然后让原来的和复制的节点一一对应,
使用HashMap进行K-V映射,然后遍历一次,使得random指针的进行深复制
/**
* Definition for singly-linked list with a random pointer.
* class RandomListNode {
* int label;
* RandomListNode next, random;
* RandomListNode(int x) { this.label = x; }
* };
*/
public class Solution {
public RandomListNode copyRandomList(RandomListNode head) {
RandomListNode copyHead = null, Nnext = head, pre = null, next = null;
HashMap<RandomListNode, RandomListNode> map = new HashMap<>();
while(Nnext != null){
next = new RandomListNode(Nnext.label);
if(copyHead == null){
pre = copyHead = next;
}else{
pre.next = next;
pre = pre.next;
}
map.put(Nnext, pre);
Nnext = Nnext.next;
}
Nnext = head;
while(Nnext != null){
pre = map.get(Nnext);
next = map.get(Nnext.random);
pre.random = next;
Nnext = Nnext.next;
}
return copyHead;
}
}
在leetcodeOJ上的Discuss有一个O(N)时间复杂度的,O(1)空间复杂度的C++,
经过一次模拟之后,里面的的技巧非常好,原来的链表假设是
将深复制的节点一次跟在原来相应节点的后面
那么现在容易知道,深复制的node的random指向的是会是相应原来节点random节点的next节点了,
一次遍历就可以将原始node,和深复制的node分离和合并
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == NULL) return NULL;
RandomListNode *p = head;
do {
RandomListNode *q = p->next;
p->next = new RandomListNode(p->label);
p->next->next = q;
p = q;
} while(p != NULL);
p = head;
do {
p->next->random = (p->random == NULL) ? NULL : p->random->next;
p = p->next->next;
} while(p != NULL);
p = head;
RandomListNode *r = head->next;
for(RandomListNode *q = r;;) {
p->next = q->next;
p = p->next;
if(p == NULL) break;
q->next = p->next;
q = q->next;
}
return r;
}