复制特殊链表

12 篇文章 0 订阅

转自<http://blog.sina.com.cn/s/blog_69824c1f0100v4ob.html>

struct node
        {
             int data;
             struct node * next;
             struct node * random;
        };

        本题来源是ms的一道面试题,要求是将一条有特殊结构的链表进行复制,链表的结构如上,除了正常的2个域之外,多了一个random,它代表一个指向链表 上某一任意节点的指针,要求将该链表复制。如图,其中实线表示next域,虚线表示random域。

拷贝特殊链表,有随机指针 - 飞云 - 我是飞云


        难点分析:本题最难的部分就在于如何将random域完好无损的完全拷贝复制到新的链表之上,对于普通链表一个while循环拷贝就可以搞定,但是这里似乎不可行。

        突破点:如何保存或记录random域可以作为一个思考的参考点,下面提供2种解法:
        1. hash缓存: 我们可以定义一个hash表,key为被拷贝链表中Node的地址,value为新的拷贝链表中Node的值。下面将在伪代码中进一步说明

        伪代码如下:
        struct node * old_list;
        struct node * new_list;

        hash ht;
        while( old_list != NULL )
        {
            if( ht.get(old_list) == NULL )   
        // 当前节点没有被复制过,则拷贝节点,同时将原节点的地址作为key,插入hash表
            {
            new_node = copy(*old_list);
            ht.set(old_list, new_node);
        }
        else    // 已经存在则直接将该节点读出
        {
            new_node = ht.get(old_list);
        }
          // 并将新复制的节点插入链表
          insert(new_list, new_node);
   
          if( ht.get(old_list->random) == NULL )   
          // 如果ht的random不存在,那么产生一个random node,并放入hash表
          {
                random_node = copy(*(old_list->random));
                ht.set(old_list->ramdon,random_node);
        }
            else    //否则从hash表中读出random
          {
              random_node = ht.get(old_list->random);
            }
            // 将random域进行填充
            new_node->random = random_node;
        }

        这样可以看出,因为地址值是唯一存在的,所以Hash函数的设计可以保证每个节点的值都会被一一映射,并且由于每一个节点都只会被复制一次,并且在代码的遍历过程中就已经完全复制好,空间复杂度为O(n),时间复杂度为O(n)

        2. 用一个图的方法看的比较清楚,首先在遍历原来链表的过程中,插入新的节点,比如A_N是copy(A_O)的,同时将A_N->next = A_O->next; A_O->next = A_N;通过一个遍历,我们就可以将链表复制成图中的样子。在完成next域的链接后,需要开始做random域的复制。

拷贝特殊链表,有随机指针 - 飞云 - 我是飞云


        在实现了next的结构之后,我们需要开始对new_list的random域和next域进行赋值。
        那么有: A_N->random = A_O->random->next;
        入图所示:A_O->random为C_O,C_O的next为C_N,这样A_N->random = C_N;
        对于 A_N->next = A_N->next->next;即B_N;
        该算法复杂度为O(N),空间复杂度为O(1),除了新拷贝的空间之外没有额外地址;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值