zoukankan      html  css  js  c++  java
  • 【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指针是不能同时进行的。因为有可能有如下情况:

    在建立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 };
  • 相关阅读:
    071:【Django数据库】ORM聚合函数详解-Avg
    实战:百度知道营销,自问自答技巧(下)
    实战:百度知道营销,自问自答技巧(上)
    QQ群排名霸屏技术居然是这样简单
    百度云盘,资源引流的温床,你绝对值得拥有!
    PC时代 常用搜索引擎高级指令 勿忘
    免费影视资源 日引不说几百上千 反正绝对不会是零
    QQ兴趣部落 大批量引流实战技巧
    新媒体运营之话说如此操作更容易出站街号。
    QQ群认证 人数再度扩容 权限随之升级
  • 原文地址:https://www.cnblogs.com/sunshineatnoon/p/3735094.html
Copyright © 2011-2022 走看看