• OJ第三篇


    文章目录

    随机链表的复制

    链接:随机链表的复制
    在这里插入图片描述

    这个题简单而言就是它给一个链表,每个结点包含两个指针,分别指向下一个和一个随机的结点(也有可能指向空),你要做的就是复制这个链表,使你创建的链表的结点也分别指向你创建的链表的结点的下一个值和对应的那个随机值。

    这道题的难点是原链表中那个随机指针的指向在新链表中并不能用,你得找到新链表中对应的那个位置才可以,当然我们可以暴力求解,就是先复制链表的data和next值,先不管random,创建好了之后就去找原链表中每个结点的random值是NULL还是第几个结点的指针,两个指针指向两个链表中的对应相同的位置去找。

    struct Node* copyRandomList(struct Node* head) {
     struct Node*cur=head;
     struct Node*newhead=NULL,*tail=NULL;
     //下边是去创建新链表
     while(cur!=NULL){
         struct Node*tmp=(struct Node*)malloc(sizeof(struct Node));
         tmp->val=cur->val;
         tmp->next=NULL;
         tmp->random=NULL;
         if(newhead==NULL){
         newhead=tail=tmp;
         }
         else{
             tail->next=tmp;
             tail=tail->next;
         }
         cur=cur->next;
     }
    //下边管random
    cur=head;
    struct Node*copycur=newhead;
    while(cur!=NULL){
            struct Node*tmp1=head;
            struct Node*tmp2=newhead;
            while(cur->random!=tmp1){//去找对应的位置,如果为空就是最后一个位置,也能找到
                tmp1=tmp1->next;
                tmp2=tmp2->next;
            }
            copycur->random=tmp2;
        cur=cur->next;
        copycur=copycur->next;
    }
    return newhead;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    上面是暴力求解的过程,时间复杂度都已经O(N^2),那么如何简化一下算法呢?我们的问题是找不到random的值,那我们就想法让它有迹可循,方法是:我们把复制的结点创建到原链表的每个对应的结点的后面,那就不管next,先管random,random的值就是原结点的random的值的下一个,之后再把新结点摘下来,组成一个新的链表,恢复原链表,可能这么说有点抽象,我们画图来看一下

    在这里插入图片描述

    struct Node* copyRandomList(struct Node* head) {
        //先在每个结点后面添加一个相同的结点
    	struct Node* cur=head;
        while(cur){
            struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));
            newnode->val=cur->val;
            struct Node*next=cur->next;
            cur->next=newnode;
            newnode->next=next;
            cur=next;
        }
        //处理拷贝结点的random
        cur=head;
        while(cur){
            if(cur->random==NULL){
                cur->next->random=NULL;
            }
            else{
    cur->next->random=cur->random->next;
            }
            cur=cur->next->next;
        }
    //把拷贝的结点摘下来并且恢复原链表
    cur=head;
    struct Node*newhead=NULL,*tail=NULL;
    while(cur){
        struct Node*copy=cur->next;
        struct Node*next=copy->next;
        if(newhead==NULL){
            newhead=tail=copy;
        }
        else{
            tail->next=copy;
            tail=tail->next;
            tail->next=NULL;
        }
        cur->next=next;
        cur=next;
    }
    return newhead;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    【代码随想录算法训练营】第48天 | 第九章 动态规划(九)+ 复习第20天 第六章 二叉树(四)
    挂脖式运动蓝牙耳机推荐,目前适合运动佩戴的五款耳机推荐
    3.3-DIY一个Base Image
    Canal整合SpringBoot详解(二)
    vue blob实现自定义多sheet数据导出到excel文件
    双token三验证和微信登录流程图
    【无标题】Angular/Material
    面试问到MySQL模块划分与架构体系怎么办
    swift 页面跳转
    CVL网卡的ADQ特性在SPDK的NVMF测试中的应用实例 - 上篇
  • 原文地址:https://blog.csdn.net/2201_76024104/article/details/133816827