剑指 offer 35 leetcode105. 复制带随机指针的链表

题目描述:给出一个链表,每个节点包含一个额外增加的随机指针可以指向链表中的任何节点或空的节点。返回一个深拷贝的链表。 

首先,我先解释一下题目的意思。就是完全按照给出的链表的关系复制链表,比如,原链表中值为1的节点的next指向的是值为2的节点,随机指针指向值为3的节点,那么,复制之后,还是应该满足这样的指向关系, 


所谓深拷贝,就是开辟了内存,新对象指向新的内存,而不是和原对象一样指向同一片内存,两个对象的各自改变,不会互相影响

我们当然第一想法就是一个个复制节点,但是难度在于什么呢?复制前面节点的时候并不知道他要指向的节点(不论是随机还是next)在哪个地址。所以,直接简单粗暴复制是肯定不行的。

1、哈希表1

思路:创建一个键值和值均为RandomListNode*型哈希表,需要O(n)的空间复杂度,o(n)的时间复杂度

1、首先复制数据值和值间的next关系

2、复制random关系(此题的难点)

此方法非常简洁,体会到了哈希表的强大。

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        map<RandomListNode*,RandomListNode*>temp;
        RandomListNode*s=new RandomListNode(0);
        RandomListNode*head=s;
        RandomListNode*cur=pHead;
        //复制结点值和next关系
        while(cur!=NULL)
        {
          RandomListNode*newnode=new RandomListNode(cur->label);
            temp[cur]=newnode;//原链表结点对应的复制链表结点,关键点所在
            s->next=newnode;
            s=s->next;
            cur=cur->next;
        }
        cur=pHead;//复制随机指针 
        while(cur!=NULL)
        {
            temp[cur]->random=temp[cur->random];//即newnode->random=temp[cur->random],关键点所在
            cur=cur->next;
        }
        return head->next;
   }
};

2、非哈希表  (剑指offer解法)     o(1)的空间复杂度,o(n)的时间复杂度 

假设开始数组是1->2->3->4  。

1、第一遍扫的时候巧妙运用next指针,扫描过程中 先建立copy节点 1->1`->2->2`->3->3`->4->4`, 

2、 第二遍copy的时候去建立边的copy, 拆分节点, 一边扫描一边拆成两个链表,这里用到两个dummy node。第一个链表变回  1->2->3 , 然后第二变成 1`->2`->3`  。如下图所示


RandomListNode *copyRandomList(RandomListNode *head) {
        // write your code here
          if(head==NULL){
             return head;
         }
         RandomListNode*p=head;
        while(p!=NULL){
          RandomListNode*newnode=new RandomListNode(p->label);
          newnode->next=p->next;
          p->next=newnode;
          p=newnode->next;
        }
        //复制random
        p=head;
        while(p!=NULL&&p->next!=NULL){
            p->next->random=p->random==NULL?NULL:p->random->next; //不懂看下图
            p=p->next->next;
        }
       //将链表分成两个链表
         p=head;
         RandomListNode* newnode=head->next;
         RandomListNode*q=newnode;
        while(p!=NULL){
            p->next=newnode->next;
            if(newnode->next!=NULL)
            newnode->next=newnode->next->next;
            p=p->next;
            newnode=newnode->next;
        }
        return q;
    }    
};

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值