【leetcode】Copy List with Random Pointer

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指针是不能同时进行的。因为有可能有如下情况:

【leetcode】Copy List with Random Pointer

在建立3'的random指针的时候通过3'当前的random指针找到3,又通过3的random指针找到1,但是如果1的next指针已经被改为指向2,而不再是1',那么就没办法找到3'真正的random指针1'了,所以恢复原来链表的next指针,只能在新链表完全建立好以后进行。那么就需要一个结构来存储原来链表的next指针信息,这里采用一个map:oldlistnext保存。

所以算法分为3个循环:

第一个循环,建立新的链表,并且把新链表中各个节点的random指针指向原来链表对应的节点,原来链表的next指针指向新链表的对应节点,如下图所示:

【leetcode】Copy List with Random Pointer

图中橙色是原来链表的next指针,绿色是新建链表的random指针,蓝色虚线表示新建链表的next指针。

第二个循环,恢复新建链表的next和random指针:new_list_p->next = new_list_p->next->next;new_list_p->random = new_list_p->random->random->next;如下图所示:

【leetcode】Copy List with Random Pointer

第三个循环,恢复原来链表的next指针,old_list_p->next = oldlistnext[old_list_p],如下图所示:

【leetcode】Copy List with Random Pointer

当然,上述过程中要注意各种边界情况的考虑。

代码如下:

 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 };

 

 

你可能感兴趣的:(LeetCode)