复杂链表的复制(每日一题)

目录

一、问题描述

二、思路一

2.1 分析

2.2 代码

三、思路二

3.1 分析

3.2 代码 


一、问题描述

oj链接:剑指 Offer 35. 复杂链表的复制 - 力扣(LeetCode)

二、思路一

2.1 分析

     思路一的解法相对繁琐,一般我们使用思路二,具体步骤如下:

  1. 创建一个新链表,新链表每个节点的val值以及next的值都与原链表保持一致,random值暂且不管。
  2. 创建两个数组,一个数组num1存储原链表中每个结点的地址,另一个数组num2存储新链表中每个结点的地址。
  3. 原链表中结点的random对应于数组num1某个下标中的地址,记录下标,新链表的对应结点的random值即为数组num2中相同下标的地址。

具体图解如下:

2.2 代码

class Solution {
public:
    Node* copyRandomList(Node* head) {
       if(head==NULL)
       {
           return NULL;
       }
       Node* cur = head;
       Node* newhead = NULL,*newtail = NULL;
       int count = 0;
       while(cur)
       {
           count++;
           Node* newnode = (Node*)malloc(sizeof(Node));
           if(newnode == NULL)
           {
               perror("malloc fail");
               exit(-1);
           }
           newnode->val = cur->val;
           newnode->next = NULL;

           if(newhead == NULL)
           {
               newhead = newtail = newnode;
           }
           else
           {
               newtail->next = newnode;
               newtail = newtail->next;
           }
           cur = cur->next;
       }
       Node* num1[count];
       Node* num2[count];
       int i = 0;
       newtail = newhead;
       cur = head;
       while(cur)
       {
           num1[i] = cur;
           i++;
           cur = cur->next;
       }
       i = 0;
       while(newtail)
       {
           num2[i] = newtail;
           i++;
           newtail = newtail->next;
       }
       cur = head;
       newtail = newhead;
       int x = 0;
       while(cur)
       {
           if(cur->random==NULL)
           {
               newtail->random = NULL;
           }
           else
           {
               for(x = 0;x<i;x++)
               {
                   if(cur->random == num1[x])
                   {
                      newtail->random = num2[x];
                      break;
                   }  
               }
           }
           cur = cur->next;
           newtail = newtail->next;
       }
       return newhead;
    }

};

三、思路二

3.1 分析

     我们会发现在上述思路中最大的问题在于原链表中的结点与新链表的结点之间没有联系,所以我们就想到了一个办法,把新的拷贝节点连接到原链表的结点的后面。

     具体步骤如下:

  1. 拷贝节点链接在原结点的后面。
  2. 拷贝节点的random等于原结点的random->next。
  3. 拷贝节点解下来,链接成一个新链表,恢复原链表。

 

 

3.2 代码 

class Solution {
public:
    Node* copyRandomList(Node* head) {
       
      //1.插入拷贝节点到原结点的后面
       Node* cur = head;
       Node* copy = NULL;
       while(cur)
       {
           //插入
           copy = (Node*)malloc(sizeof(Node));
           if(copy==NULL)
           {
               perror("malloc fail");
               exit(-1);
           }
           copy->val = cur->val;
           copy->next =NULL;

           Node* next = cur->next;
           copy->next = next;
           cur->next = copy;

           cur = next;

       }

       //处理拷贝的结点的random
       cur = head;
       while(cur)
       {
           copy = cur->next;
           if(cur->random==NULL)
           {
               copy->random = NULL;
           }
           else
           {
               copy->random = cur->random->next;
           }
           
           cur = copy->next;
       }
       
       //拷贝节点解下来,链接成新链表,并且恢复原链表
       cur = head;
       Node* newhead = NULL,*newtail = NULL,*next = NULL;
       
       while(cur)
       {
           copy = cur->next;
           next = copy->next;
           if(newhead == NULL)
           {
               newhead = newtail = copy;
           }
           else
           {
               newtail->next = copy;
               newtail = newtail->next;
           }
           //恢复原链表
           cur->next = next;
           cur = next;
           
            
       }
       return newhead;
    }

};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值