随机链表的复制(Java详解)

简介: 随机链表的复制(Java详解)

一、题目描述

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

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

例如,如果原链表中有 XY 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x y ,同样有 x.random --> y

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0n-1);如果不指向任何节点,则为  null

你的代码 接受原链表的头节点 head 作为传入参数。

示例:

二、题解

题目分析:

给定的链表节点包含三个部分:

class Node {
    int val;
    Node next;
    Node random;
    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}

(1)val:当前节点存储的值

(2)next:指向下一节点

(3)random:随机指针 可以指向链表中的任何节点或空节点

复制这个随机链表,即每个新节点的值与其对应的原节点的值相同。新节点的 next 指针和 random 指针也都指向对应的新节点

思路分析:

若复制普通链表,我们只需遍历原链表,在遍历过程中创建新节点,再通过前驱节点prev指向当前新节点,即可实现普通链表的复制。而本题中新增了 random,由于 random 可以指向链表中任意节点或空节点,意味着我们不仅要实现 前驱节点对当前节点的指向,也要实现 前驱节点对随机节点的指向

我们可以利用哈希表,通过构建原链表节点与新链表节点的键值对映射关系来解决该题

具体实现:

(1)根据原链表节点的值创建新链表,并把原链表的节点和创建的新链表节点放入哈希表 map

(2)遍历原链表,根据原链表节点cur的next、random找到新链表节点node的next、random指向,并确定新链表的next、random

通过原链表节点找到新链表节点:map.get(cur),新链表节点的next:map.get(cur).next

通过原链表节点的next找到新链表节点的next:map.get(cur.next)

确定新链表的next:map.get(cur).next = map.get(cur.next)

通过原链表节点找到新链表节点:map.get(cur),新链表节点的random:map.get(cur).random

通过原链表节点的next找到新链表节点的random:map.get(cur.random)

确定新链表的random:map.get(cur).random = map.get(cur.random)

(3)返回新链表的头节点

通过原链表的头节点,找到新链表的头节点,并返回

代码实现:

class Solution {
    public Node copyRandomList(Node head) {
        //根据原链表创建新链表
        Node cur = head;
        Map<Node,Node> map = new HashMap<>();
        //遍历原链表,创建新链表,并将其放入map中
        while(cur != null){
            Node node = new Node(cur.val);
            map.put(cur,node);
            cur = cur.next;
        }
        //根据原链表节点的next、random修改新链表节点的next、random
        cur = head;
        while(cur != null){
            map.get(cur).next = map.get(cur.next);
            map.get(cur).random = map.get(cur.random);
            cur = cur.next;
        }
        //返回新链表的头节点
        return map.get(head);
    }
}

题目来自:

138. 随机链表的复制 - 力扣(LeetCode)

目录
相关文章
|
2月前
|
Java
java数据结构,双向链表的实现
文章介绍了双向链表的实现,包括数据结构定义、插入和删除操作的代码实现,以及双向链表的其他操作方法,并提供了完整的Java代码实现。
java数据结构,双向链表的实现
|
26天前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
21 3
|
5月前
|
Java
环形数组链表(java)
环形数组链表(java)
|
3月前
|
存储 Java
|
3月前
|
存储 Java
java实现单链表的创建、增、删、改、查
这篇文章详细介绍了Java中如何实现单链表的创建以及对单链表进行增加、删除、修改、查询等操作的方法,并提供了相应的代码示例。
java实现单链表的创建、增、删、改、查
|
3月前
|
存储 Java 开发者
揭秘!HashMap底层结构大起底:从数组到链表,再到红黑树,Java性能优化的秘密武器!
【8月更文挑战第24天】HashMap是Java集合框架中的核心组件,以其高效的键值对存储和快速访问能力广受开发者欢迎。在JDK 1.8及以后版本中,HashMap采用了数组+链表+红黑树的混合结构,实现了高性能的同时解决了哈希冲突问题。数组作为基石确保了快速定位;链表则用于处理哈希冲突;而当链表长度达到一定阈值时,通过转换为红黑树进一步提升性能。此外,HashMap还具备动态扩容机制,当负载因子超过预设值时自动扩大容量并重新哈希,确保整体性能。通过对HashMap底层结构的深入了解,我们可以更好地利用其优势解决实际开发中的问题。
94 0
|
3月前
|
存储 Java
【Java集合类面试十】、HashMap中的循环链表是如何产生的?
在多线程环境下,HashMap在扩容时如果发生条件竞争,元素的插入顺序可能形成循环链表,导致死循环。
|
3月前
|
存储 Java
java实现双向链表的增删改查
这篇文章展示了如何在Java中实现双向链表的增加、删除、修改和查询操作,并通过代码示例演示了在双向链表中存储和操作学生信息的过程。
|
3月前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
53 0
|
3月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
42 0