leetcode 138随机链表的复制

cpp 复制代码
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution {
public:
    unordered_map<Node*,Node*>cacheNode;
    Node* copyRandomList(Node* head) {
        Node *p = head;
        while(p!=nullptr){
            cacheNode[p] = new Node(p->val);
            p = p->next;
        }
        p = head;
        while(p!=nullptr){
            cacheNode[p]->next = cacheNode[p->next];
            cacheNode[p]->random = cacheNode[p->random];
            p = p->next;
        }
        return   cacheNode[head];
    }
};

这题的方法可以精简成一句话:

先用哈希表建立"原节点 → 新节点"的映射,再根据原链表的 next 和 random 去连接新链表。

方法流程:

复制代码
// 第一遍:创建新节点
while (p != nullptr) {
    cacheNode[p] = new Node(p->val);
    p = p->next;
}

// 第二遍:连接 next 和 random
p = head;
while (p != nullptr) {
    cacheNode[p]->next = cacheNode[p->next];
    cacheNode[p]->random = cacheNode[p->random];
    p = p->next;
}

核心映射关系要记住:

复制代码
原节点 p         -> cacheNode[p]

原 p->next       -> cacheNode[p->next]

原 p->random     -> cacheNode[p->random]

易错点

最容易错的是第二遍写成:

复制代码
cacheNode[p]->next = p->next;       // 错
cacheNode[p]->random = p->random;   // 错

这样新节点又指回原链表了,不是深拷贝。

必须写:

复制代码
cacheNode[p]->next = cacheNode[p->next];
cacheNode[p]->random = cacheNode[p->random];

第二个易错点是:

复制代码
cacheNode[p] = new Node(p->val);

这里只复制了:

复制代码
val

还没有复制 next 和 random,所以必须有第二遍连接。

第三个易错点是理解:

复制代码
cacheNode[p->random]

它不是 random 本身,而是:

原 random 节点对应的新节点。

比如:

复制代码
A.random -> C

那么:

复制代码
cacheNode[A]->random = cacheNode[C];

得到:

复制代码
A'.random -> C'

复杂度

两次遍历都是 O(n):

复制代码
时间复杂度:O(n)

哈希表存了 n 个映射:

复制代码
空间复杂度:O(n)

最后可以直接背这个模板:

复制代码
unordered_map<Node*, Node*> map;

// 1. 创建
map[原节点] = 新节点;

// 2. 连接
map[p]->next = map[p->next];
map[p]->random = map[p->random];

// 3. 返回
return map[head];

口诀:

第一遍造节点,第二遍连关系;所有旧指针,都要通过 map 找到对应的新节点。

相关推荐
Rain的Java大神之路12 小时前
LeetCode 37 解数独面试攻略:回溯 + 位掩码 + MRV,从暴力到毫秒级求解
java·后端·leetcode
NEFU_Jyj12 小时前
贝尔数(组合数学)
算法
希和202713 小时前
C语言程序设计题|有序数组插入数字冒泡排序
c语言·数据结构·算法
Pniubi13 小时前
力扣73 矩阵置零
算法·leetcode·矩阵
布莱克6051 天前
C++ 中 map 的 insert 与 emplace:key 已存在时会覆盖吗?
开发语言·数据结构·c++·算法·map
D e re k ZH1 天前
C++ 系统学习手记:从语法细节到工程实践
开发语言·数据结构·c++·算法
石小石Orz1 天前
AI 正在蚕食我们的编码能力
前端·后端·算法
民乐团扒谱机1 天前
【微实验】NSGA-II(非支配排序遗传算法)——解决多目标优化问题的“自然选择模拟器”
linux·人工智能·算法
青少儿编程课堂1 天前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:中缀表达式求值解析
c++·python·算法·bfs·信息学竞赛