[路飞]_算法·每日解读--复制带随机指针的链表

171 阅读3分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

题解: leetcode复制带随机指针的链表

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

示例:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

题意可分解为两部分:其一复制链表,其二复制的链表带有随机指向

接下来选择解题方法,理清思路:

  1. 首先第一步,只考虑进行原链表的复制操作:

    因为是深拷贝,所以我们需要创建一个新的链表用于存储复制后的节点

    if(!head) return null;
    let p = head,   //p指向链表的头节点
        q;          //声明一个变量p,后面用于存储新创建的新的链表
    //执行赋值操作
    while(p){
        q = new ListNode(p.val);  //直接将p的val传入
        q.next = p.next;          //将p.next的指向赋值于q.next,令其指向相同的下一个节点
        q.random = p.random;
        
        //接下来,切断原链表,将q节点依次插入到父节点p节点的后面
        p.next = q;
        //移动变量p的指针指向,进行接下来的循环操作
        p = q.next
    }
    

    在这里,一定要搞清楚,①指针的指向问题,②指针的指向切换问题

  2. 完成原链表的赋值操作后,重新让变量 p 指向 head.next (此时的 head 已经是包含双节点的链表),接下来调整q链表中每个节点random的指向

    p = head.next;
    while(p){
        p.random && (p.random = p.random.next);  
        (p = p.next) && (p = p.next);       //等同于下面的if语句
        //if(p.next) p = p.next.next
    }
    

    注意p = p.next.next需要满足的条件

  3. 完成 random 随即指针的指向后,接下来进行拆分链表操作,分成原链表和克隆节点链表

    p = q = head.next;      //将p和q同时指向head.next节点,先锁定head.next节点,避免丢失,同时p来作为q的链表头节点,q为定位指针(二者可以互换?)
    while(q.next){
        head.next = head.next.next;     //改变head节点的指向
        q.next = q.next.next;
        //以上两步改变head.next和q.next的指向,下面两步是移动head和q的指向,后移一步
        head = head.next;
        q = q.next;
    }
    //最后需要重置head.next为null
    head.next = null;
    return p;
    

    调整指针的指向和指针的next赋值,最容易搞混

👆 👆 以上就是个人对【复制带随机指针的链表】的代码解法和方法解读。

迷惑重重,就用蜡笔头,一键三连哟!!!

完成代码请移步: 稍后添加