[NEO解题报告]《Leetcode》138. 复制带随机指针的链表

1. 题目信息

1.1 题目描述

题目链接: 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.2 测试用例

  • 示例 1:
    在这里插入图片描述
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
  • 示例 2:

在这里插入图片描述

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
  • 示例 3:
    在这里插入图片描述
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
  • 示例 4:
输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
  • 提示:
0 <= n <= 1000
-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。

2. 题目分析

2.1 哈希节点映射方法

两步走即可,第一遍直接复制节点的val、random, 第二遍更新random指向新节点;

  • 先复制节点, 并记录每个老节点对应的新节点的映射关系, 新节点的random指向原来的老节点;
  • 遍历新节点, 对每一个random 更新成新的节点地址;

2.2 回溯+哈希

递归处理即可, 用哈希记录已经生成的节点映射关系, 即记录 老节点 => 新节点 的映射关系 ;

  • 节点映射关系不存在, 则生成节点并递归调用 ;
  • 节点映射存在直接返回节点地址;

3. 代码详情

3.1 C++

3.1.1 哈希节点映射方法

class Solution {
public:
    Node* copyRandomList(Node* head) {
        // 执行用时:8 ms, 在所有 C++ 提交中击败了88.52%的用户
        // 内存消耗:11.3 MB, 在所有 C++ 提交中击败了19.11%的用户
        if (head == nullptr) {
            return nullptr;
        }
        
        Node *newHead = new Node(*head);
        unordered_map<Node*, Node*> oldToNew{{head, newHead}};

        Node *oldNode = head->next;
        Node *newNode = newHead;
        while (oldNode != nullptr) {
            newNode->next = new Node(*oldNode);
            oldToNew[oldNode] = newNode->next;
            oldNode = oldNode->next;
            newNode = newNode->next;
        }
        // update random
        newNode = newHead;
        while (newNode != nullptr) {
            newNode->random = oldToNew[newNode->random];
            newNode = newNode->next;
        }
        return newHead;
    }
};

3.1.2 回溯+哈希

class Solution {
public:
    unordered_map<Node*, Node*> cachedNode;

    Node* copyRandomList(Node* head) {
        if (head == nullptr) {
            return nullptr;
        }
        if (!cachedNode.count(head)) {
            Node* headNew = new Node(head->val);
            cachedNode[head] = headNew;
            headNew->next = copyRandomList(head->next);
            headNew->random = copyRandomList(head->random);
        }
        return cachedNode[head];
    }
};
  • 作者:LeetCode-Solution
  • 链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/fu-zhi-dai-sui-ji-zhi-zhen-de-lian-biao-rblsf/

3.2 Python

4. 系列文章

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逸云沙鸥のIHave@Dream

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值