问题分析:
一个复杂的链表,节点中有一个指向本链表任意某个节点的随机指针(也可能为空),求这个链表的深度拷贝
思路:
此题有两种方法,一种是按照原链表next的顺序依次创建节点,并处理好新链表的next指针,同时把原节点与新节点的对应关系保存到一个hash_map中,然后第二次循环将random指针处理好。这种方法的时间复杂度是O(n),空间复杂度也是O(n)。
第二种方法则是在原链表的每个节点之后插入一个新的节点,这样原节点与新节点的对应关系就已经明确了,因此不需要用hash_map保存,但是需要第三次循环将整个链表拆分成两个。这种方法的时间复杂度是O(n),空间复杂度是O(1)。
但是利用hash_map的方法具有其他的优点,如果在循环中加入一个判断,就可以检测出链表中是否有循环;而第二种方法则不行,会陷入死循环。
/**
* 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) {
HashMap<RandomListNode,RandomListNode> map=new HashMap<>();
RandomListNode cur=head;
//第一步,将结点存入哈希表
while(cur!=null){
RandomListNode newNode=new RandomListNode(cur.label);
map.put(cur,newNode);
cur=cur.next;
}
//
cur=head;
while(cur!=null){
RandomListNode node=map.get(cur);
node.next=map.get(cur.next);
node.random=map.get(cur.random);
cur=cur.next;
}
return map.get(head);
}
}
方法二:c++
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head==NULL){
return NULL;
}
RandomListNode *now = head; //复制各个节点
while(now){
RandomListNode *copy = new RandomListNode(now->label);
copy->next = now->next;
now->next = copy;
now = copy->next;
}
for(now=head; now; now=now->next->next){ //复制random指针域
now->next->random = (now->random)?now->random->next:NULL;
}
RandomListNode* h = head->next; //断开成两个链表
RandomListNode* t = h;
RandomListNode* tail = head;
for(;;){
tail->next = t->next;
tail = tail->next;
if(tail==NULL){
break;
}
t->next = tail->next;
t = t->next;
}
return h;
}
};