图式详解复制带随机指针的链表

1、题目描述

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的深拷贝
在这里插入图片描述

2、分析

这里需要注意,要返回的链表是旧链表的深拷贝,所以新链表的数据域必须是一样的。再来看next域和随机指针域呢?也一样吗?
当然是不可以,next域和random存放的都是地址,物理地址是唯一标识,如果地址一样那后果就不可设想了。也就是说新的链表种要满足的就是以下条件:

  • 数据域一模一样
  • 新链表的每个节点next域保留的下一个节点对应一样的的,比如原链表种2节点后面是4
    在这里插入图片描述
    新的链表中,2后面对应的仍然要是4,需要保持一个这样的对应关系
    在这里插入图片描述
  • 对于随机指针域的要求也和next域的要求一样,必须对应。
3、具体做法:
  • 将复制链表的节点一个个插入到原链表中,使得旧链表和复制链表串为一个链表。具体:

A:定义新的节点node ,把random域暂时置为null

Node node = new Node(cur.val,cur.next,null)
//需要下这注意这一句,这里复制后的新链表的每一个节点的next域都已经保存了下一个节点的地址值,也就是新节点的next域已经串好了。

B: 定义cur遍历旧链表,定义temp指向旧链表 cur的下一个节点,将复制的节点插入到旧链表中。由A步骤我们知道复制链表的next域已经连起来了,这里只需要搞定原链表的next域即可。

Node cur = this.head;
Node temp = cur.next;
//把复制的节点串上去
cur.next = node;
//更新一下当前的cur
cur = temp;

在这里插入图片描述
将所有的节点串好后
在这里插入图片描述
C:借助这个合成的链表处理random域,再次把cur拉到头前,遍历合成的这个链表的旧的部分(就是保证cur每次走两步)

if(random != null){
	cur.next.random = cur.random.next;
}

也就是这里我们借助了原链表,当这个旧链表的随机指针有指向别的节点的时候,在这个合成链表中,旧链表的random域指向的节点,和新链表random逻辑上需要对应,简单讲,你会从图中发现,如果当前cur的random域不为null,那这个节点的下一个节点,也就是我们要复制的这个节点也不为null,并且这个节点的random域所指向节点,其下一个节点就是复制节点random应该指向的值,借用这个规则可以处理好所有的random。

在这里插入图片描述

D:拆分出复制后的链表

cur = head;
Node newHead = cur.next;
 while(cur.next != null){
     Node temp = cur.next;
     cur.next = temp.next;
     cur = temp;
        }

java描述的源代码

public Node copyRandomList(Node head) {
        if(head == null){
            return null;
        }
        Node cur = head;
        while(cur != null){
            Node node = new Node(cur.val,cur.next,null);
            Node temp = cur.next;
            cur.next = node;
            cur = temp;
        }
        cur = head;
        while(cur != null){
            if(cur.random != null){
                cur.next.random = cur.random.next;
            } else {
                cur.next.random = null;
            }
            cur = cur.next.next;
        }
        cur = head;
        Node newHead = cur.next;
        while(cur.next != null){
            Node temp = cur.next;
            cur.next = temp.next;
            cur = temp;
        }
        return newHead;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值