【算法--链表】138.随机链表的复制--通俗讲解
算法通俗讲解推荐阅读
【算法–链表】83.删除排序链表中的重复元素–通俗讲解
【算法–链表】删除排序链表中的重复元素 II–通俗讲解
【算法–链表】86.分割链表–通俗讲解
【算法】92.翻转链表Ⅱ–通俗讲解
【算法–链表】109.有序链表转换二叉搜索树–通俗讲解
【算法–链表】114.二叉树展开为链表–通俗讲解
【算法–链表】116.填充每个节点的下一个右侧节点指针–通俗讲解
通俗易懂讲解“随机链表的复制”算法题目
一、题目是啥?一句话说清
给你一个链表,每个节点有一个随机指针,指向链表中的任意节点或空。你需要深拷贝这个链表,创建全新节点,并正确设置next和random指针。
示例:
- 输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
- 输出:复制后的链表,其中每个新节点的random指向新链表中的对应节点。
二、解题核心
使用哈希表来映射原节点到新节点。首先遍历原链表,创建所有新节点并存储映射关系。然后再次遍历原链表,根据映射关系设置新节点的next和random指针。
这就像先复制所有人的身份证(创建新节点),然后根据原关系网(原链表)来建立新关系网(新链表)。
三、关键在哪里?(3个核心点)
想理解并解决这道题,必须抓住以下三个关键点:
1. 哈希表的映射作用
- 是什么:使用哈希表存储原节点和新节点的对应关系,这样可以通过原节点快速找到新节点。
- 为什么重要:当设置random指针时,我们需要知道原节点对应的新节点是什么。哈希表提供了O(1)的查找效率,确保正确连接random指针。
2. 两次遍历链表
- 是什么:第一次遍历创建新节点并建立映射;第二次遍历设置指针。
- 为什么重要:第一次遍历确保所有新节点都被创建;第二次遍历利用映射正确设置random指针,因为random可能指向任何节点,需要通过哈希表找到对应的新节点。
3. 处理null指针的情况
- 是什么:如果原节点的random指针为null,新节点的random也应为null。
- 为什么重要:避免空指针异常,并确保复制准确。在访问哈希表时,需要检查原指针是否为null,否则会出错。
四、看图理解流程(通俗理解版本)
假设原链表为:A -> B -> C,其中A.random指向C,B.random指向A,C.random为null。
-
第一次遍历:创建新节点和映射
- 遍历原链表,对于每个节点,创建新节点,值相同。
- 将原节点A映射到新节点A’,原节点B映射到新节点B’,原节点C映射到新节点C’。
- 此时新节点还没有连接next和random。
-
第二次遍历:设置指针
- 再次遍历原链表,对于每个原节点,通过哈希表找到对应的新节点。
- 设置新节点的next:原节点A的next是B,所以新节点A’的next应该是B’(通过哈希表得到)。
- 设置新节点的random:原节点A的random是C,所以新节点A’的random应该是C’(通过哈希表得到)。同理,B的random是A,所以B’的random是A’。C的random为null,所以C’的random为null。
- 这样新链表就完整了。
五、C++ 代码实现(附详细注释)
#include <iostream>
#include <unordered_map>
using namespace std;// 链表节点定义