A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
好麻烦的链表题T_T
首先说一下深拷贝和浅拷贝的区别,参考这篇博文:http://www.cnblogs.com/BlueTzar/articles/1223313.html
深拷贝:在拷贝过程中,为新的变量申请新的空间,所以原来的变量不存在时,拷贝得到的变量还可以使用。
浅拷贝:在拷贝过程中,不为新变量申请新的空间,只是把原来变量的地址给新的变量,原来的变量不存在时,拷贝得到变量也不能使用了。
所以在题目中,要做到两点,第一原来的链表不能改变;第二,拷贝得到的链表要有自己完全独立的内存空间,而不是只是指向原来的链表。
解题思路思路参考:http://www.cnblogs.com/lautsie/p/3259724.html
但是这个博客有个bug,就是恢复原来链表的next指针和建立新链表的random和next指针是不能同时进行的。因为有可能有如下情况:
在建立3'的random指针的时候通过3'当前的random指针找到3,又通过3的random指针找到1,但是如果1的next指针已经被改为指向2,而不再是1',那么就没办法找到3'真正的random指针1'了,所以恢复原来链表的next指针,只能在新链表完全建立好以后进行。那么就需要一个结构来存储原来链表的next指针信息,这里采用一个map:oldlistnext保存。
所以算法分为3个循环:
第一个循环,建立新的链表,并且把新链表中各个节点的random指针指向原来链表对应的节点,原来链表的next指针指向新链表的对应节点,如下图所示:
图中橙色是原来链表的next指针,绿色是新建链表的random指针,蓝色虚线表示新建链表的next指针。
第二个循环,恢复新建链表的next和random指针:new_list_p->next = new_list_p->next->next;new_list_p->random = new_list_p->random->random->next;如下图所示:
第三个循环,恢复原来链表的next指针,old_list_p->next = oldlistnext[old_list_p],如下图所示:
当然,上述过程中要注意各种边界情况的考虑。
代码如下:
1 class Solution { 2 public: 3 RandomListNode *copyRandomList(RandomListNode *head) { 4 if(head == NULL) 5 return NULL; 6 7 RandomListNode* old_list_p = head; 8 RandomListNode* new_list_p; 9 bool has_head = 0; 10 std::map<RandomListNode *,RandomListNode *> oldlistnext; 11 12 //建立新的链表 13 while(old_list_p != NULL){ 14 RandomListNode* temp= (struct RandomListNode*)malloc(sizeof(struct RandomListNode)); 15 if(has_head == 0){ 16 new_list_p = temp; 17 has_head = 1; 18 } 19 oldlistnext.insert(std::map<RandomListNode*,RandomListNode*>::value_type(old_list_p, old_list_p->next)); 20 21 temp->label = old_list_p->label; 22 temp->next = old_list_p->next; 23 temp->random = old_list_p; 24 old_list_p->next = temp; 25 26 old_list_p = temp->next; 27 } 28 29 RandomListNode* h = new_list_p; 30 old_list_p = head; 31 32 //恢复新建链表的next和random指针 33 while(new_list_p != NULL){ 34 if(new_list_p->random->random != NULL){ 35 new_list_p->random = new_list_p->random->random->next; 36 } 37 else 38 new_list_p->random = NULL; 39 40 if(new_list_p->next != NULL) 41 new_list_p->next = new_list_p->next->next; 42 else 43 new_list_p->next = NULL; 44 45 new_list_p = new_list_p->next; 46 47 } 48 49 old_list_p = head; 50 51 //恢复原来链表的next指针 52 for(int i = 1;i <= oldlistnext.size();i++){ 53 old_list_p->next = oldlistnext[old_list_p]; 54 old_list_p = old_list_p->next; 55 } 56 57 return h; 58 } 59 };