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];
    }
};

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

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

方法流程:

复制代码
// 第一遍:创建新节点
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

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

第三个易错点是理解:

复制代码
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 找到对应的新节点。

相关推荐
shehuiyuelaiyuehao5 小时前
算法39,位运算,消失的两个数字
java·数据结构·算法
ZiLing5 小时前
2026 ROS 2 Lyrical 踩坑实录(一):编译与依赖——rosdep、现代 CMake 与 CMake 4.x
算法
Murphy_lx5 小时前
1124. 表现良好的最长时间段
c++·算法
aramae5 小时前
模拟实现strstr函数(C语言)
c语言·开发语言·算法
liliangcsdn5 小时前
因子权重矩阵处理-滞回缓冲带+降频稳定化动态重选
开发语言·python·算法
敲代码的嘎仔5 小时前
自己设计了一个兑换码算法:自增ID + Base32转码 + 按位加权签名 + 异或混淆,面试被追问细节时终于不用慌了
java·数据库·mysql·算法·微服务·面试·职场和发展
云析赢指标公式网46 小时前
文华WH6布林轨道均线强弱共振指标公式
前端·算法
多弗朗皮卡丘6 小时前
数据结构4:链表(下)
c语言·数据结构·链表
luj_17687 小时前
一线一区一变破解人盯人防守密码
开发语言·网络·c++·经验分享·算法
Wang's Blog7 小时前
Java框架快速入门: Spring Security+OAuth2之字段验证与自定义验证注解实战
java·算法·spring