Leetcode-每日一题【138.复制带随机指针的链表】

题目

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

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

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

返回复制链表的头节点。

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

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

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

示例 1:

Leetcode-每日一题【138.复制带随机指针的链表】_第1张图片

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


示例 2:

Leetcode-每日一题【138.复制带随机指针的链表】_第2张图片

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]


示例 3:

Leetcode-每日一题【138.复制带随机指针的链表】_第3张图片

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

提示:

  • 0 <= n <= 1000
  • -104 <= Node.val <= 104
  • Node.random 为 null 或指向链表中的节点。

解题思路

前置知识

Map

Map集合存储元素是成对出现的,Map集合的键是唯一的,每个键最多只能映射到一个值。 不同键映射的值是可重复的。

注意:Map集合的数据结构是针对键有效,跟值无关。而Collection集合的数据结构是针对元素有效。

Map集合的功能概述
1: 添加功能
V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null;
如果键不是第一次存储,就用值把以前的值替换掉,返回以前的值。
2: 删除功能
void clear():移除所有的键值对元素。
V remove(Object key):根据键删除键值对元素,并把值返回。
3: 判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
4: 获取功能
Set keySet():获取集合中所有键的集合
V get(Object key):根据键获取值
Set> entrySet():获取所有键值对对象的集合
Collection values():获取集合中所有值的集合
5: 长度功能
int size():返回集合中的键值对的总数

1.题目要求我们做深拷贝,也就是返回复制后的链表,但是链表中存在一个random指针指向随意的节点,所以我们并不能按顺序去复制链表,因为random指针可能会指向我们还未复制的节点,这个时候我们就要采用hashMap来辅助我们解决这个问题

2.首先我们创建一个hashMap来存放(原节点,新节点),然后我们利用for循环每次循环时创建一个新节点,让它的值等于原节点,然后将他俩一起放入hashMap中

3.我们再次使用for循环对哈市Map进行遍历,令新节点的next值等于原节点的next值( nodeMap.get(x).next = nodeMap.get(x.next)),以及令新节点的random值等于新节点的random值(nodeMap.get(x).random = nodeMap.get(x.random)),最后我们返回新链表的头节点即可( return nodeMap.get(head))

代码实现

class Solution {
    public Node copyRandomList(Node head) {
        //边界
        if (head == null){
            return null;
        }
        //遍历原链表,构造新链表的节点,存储在Map中
        //Map<原链表节点,新链表节点>
        //原1 => 新1
        Map nodeMap = new HashMap<>();
        for (Node x = head ; x != null; x = x.next){
            //构造新链表的节点
            Node node = new Node(x.val);
            nodeMap.put(x,node);
        }
        //对新链表进行链接操作
        //原1.next和新1.next一一对应
        //原1.random和新1.random一一对应
        //原1.next = 原3 => 新1.next = 新3(这个地址就可以根据原3来取得)
        for (Node x = head; x != null; x = x.next){
            //新链表的random和next和原链表一一对应
            //对于Map来说,key都是原链表的节点
            //原1.next = 原3
            nodeMap.get(x).next = nodeMap.get(x.next);
            //原1.random = 原5
            nodeMap.get(x).random = nodeMap.get(x.random);
        }
        //返回新链表的头节点,就是原链表的head的映射
        return nodeMap.get(head);
    }
}

测试结果

Leetcode-每日一题【138.复制带随机指针的链表】_第4张图片

Leetcode-每日一题【138.复制带随机指针的链表】_第5张图片

你可能感兴趣的:(leetcode,链表,算法,java,数据结构)