力扣第138题-复制带随机指针的链表

77 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

前言

力扣第138题 复制带随机指针的链表 如下所示:

image.png

一、思路

题目看起来很长,可以简单列举一下重点的信息:

  • random_index:表示指向的节点在链表中的下标(下标从0开始)
  • 目标是:深拷贝整个链表,包括random 的引用

一个非常重要的事情是,random_index 仅仅是用于描述节点中的下个随机节点的位置。实际的存储中存储的是节点的引用,也就是说 random 指向的也是某个 node。例如下图中的 [13,0] 表示当前节点为 13,下一个random 节点指向的是第一个节点 7,这里random 指向是一个实际的节点。

image.png

因为存在 random 指向的节点还未初始化的情况,如下所示:

image.png

我们需要先将所有节点都复制一遍,然后再修改新的链表中 random 的引用。此外为了知道原链表中节点与下标对应的关系和新链表中节点与下标的对应关系,我们需要用两个哈希表来存储他们。

哈希表详解如下: originalNodeMap : 存储的形式为 <Node, Integer>,表示原链表中每个节点的下标 newIndexMap:存储的形式为 <Integer, Node>,表示新链表中下标对应的节点

大致的步骤如下所示:

  1. 第一次遍历原链表:复制所有的主节点
  2. 第二次遍历原链表:根据原链表中节点的 random 指向,修改新链表中的 random 指向

二、实现

实现代码

实现的步骤与思路中保持一致:

private HashMap <Integer, Node> newIndexMap = new HashMap<>();
private HashMap <Node, Integer> originalNodeMap = new HashMap<>();

public Node copyRandomList(Node head) {
    Node targetNode = new Node(-1);
    Node tNext = targetNode;
    Node next = head;
    int count = 0;
    while (next != null){
        tNext.next = new Node(next.val);
        newIndexMap.put(count, tNext.next);
        originalNodeMap.put(next, count);
        next = next.next;
        tNext = tNext.next;
        count++;
    }
    // 拷贝指针
    tNext = targetNode.next;
    next = head;
    while (next != null){
        if (next.random != null){
            tNext.random = newIndexMap.get(originalNodeMap.get(next.random));
        }
        next = next.next;
        tNext = tNext.next;
    }
    return targetNode.next;
}

测试代码

这一题的测试用例代码会有一点长,因为涉及到随机指针的关系。

public static void main(String[] args) {
    //[[7,null],[13,0],[11,4],[10,2],[1,0]]
    Node node = new Node(7);
    Node node1 = new Node(13);
    Node node2 = new Node(11);
    Node node3 = new Node(10);
    Node node4 = new Node(2);
    node.next = node1;
    node1.next = node2;
    node1.random = node;
    node2.next = node3;
    node2.random = node4;
    node3.next = node4;
    node3.random = node2;
    node4.next = null;
    node4.random = node;
    new Number138().copyRandomList(node);
}

结果

image.png

三、总结

题目虽然击败率非常不错,但是内存的消耗还是偏大了一点,不知各位有没有更好的方式呢?

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~