🧮 Algorithm Notebook
1、算法准备
1.1 牛客网编程OJ的典型输入输出
2、算法框架
2.1 动态规划
2.1.1 斐波那契数列
2.1.2 背包问题
2.1.3 贪心算法
2.1.4 序列和数组类问题
2.1.5 编辑距离
2.1.6 高楼扔鸡蛋
2.1.7 股票问题系列通解
2.1.8 最长有效括号
2.1.9 剪绳子
2.1.10 正则表达式匹配
2.2 二分查找
2.2.1 二分查找框架
2.2.2 搜索旋转排序数组
2.3 链表
2.3.1 反转链表
2.3.2 相交链表
2.3.3 合并链表
2.3.4 链表中倒数第k个节点
2.3.5 复制带随机指针的链表
2.4 排序算法
2.4.1 常见排序算法
2.5 二叉树
2.5.1 二叉树遍历
2.5.2 岛屿问题
2.5.3 二叉树路径问题
2.5.4 构造二叉树
2.6 回溯算法
2.6.1 回溯算法解题框架
2.6.2 N皇后
2.7 数组
2.7.1 删除有序数组中的重复项
2.7.2 滑动窗口最大值
2.7.3 调整数组顺序使奇数位于偶数前面
2.7.4 螺旋矩阵
2.7.5 多数元素
2.7.6 最大数
2.7.7 和为s的两个数字
2.7.8 构建乘积数组
2.7.9 两数之和
2.8 字符串
2.8.1 最小覆盖子串
2.8.2 比较版本号
2.8.3 验证IP地址
2.8.4 基本计算器 II
2.8.5 字符串解码
2.8.6 移掉 K 位数字
2.8.7 无重复字符的最长子串
2.8.8 第一个只出现一次的字符
2.8.9 翻转字符串里的单词
2.8.10 字符串转换整数 (atoi)
2.8.11 字符串四则运算
2.9 栈
2.9.1 最小栈
2.9.2 弹出序列
2.10 数学
2.10.1 用 Rand7() 实现 Rand10()
2.10.2 只出现一次的数字
2.10.3 整数反转
2.10.4 求1+2+…+n
2.10.5 二进制中1的个数
2.10.6 幂运算
2.10.7 1~n 整数中 1 出现的次数
2.10.8 数字序列中某一位的数字
2.10.9 丑数
2.10.10 n个骰子的点数
2.10.11 圆圈中最后剩下的数字
2.10.12 不用加减乘除做加法
2.10.13 x 的平方根
2.11 设计
2.11.1 LRU 缓存机制
-
+
游客
注册
登录
复制带随机指针的链表
## 1 题目 给你一个长度为 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:** ![](/media/202201/2022-01-09_2130410.7261368158867781.png) ```txt 输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]] ``` **示例 2:** ![](/media/202201/2022-01-09_2131130.7809220936814016.png) ```txt 输入:head = [[1,1],[2,1]] 输出:[[1,1],[2,1]] ``` **示例 3:** ![](/media/202201/2022-01-09_2131310.08080883298827601.png) ```txt 输入:head = [[3,null],[3,0],[3,null]] 输出:[[3,null],[3,0],[3,null]] ``` **示例 4:** ```txt 输入:head = [] 输出:[] 解释:给定的链表为空(空指针),因此返回 null。 ``` **提示:** * 0 <= n <= 1000 * -10000 <= Node.val <= 10000 * Node.random 为空(null)或指向链表中的节点。 ## 2 问题解析 1. 首先,我们可以**忽略 `random` 指针**,然后**对原链表的每个节点进行复制**,**并追加到原节点的后面**,**将原链表和复制链表连在一起**:![](/media/202201/2022-01-09_2132230.7640217615405901.png) 2. 然后,**从前往后遍历每一个原链表节点**,**对于有 `random` 指针的节点 `p`**,**我们让它 `p.next.random = p.random.next`**,**这样我们就完成了对原链表 `random` 指针的复刻**:![](/media/202201/2022-01-09_2132350.36969955791205567.png) 3. 最后,**我们把原链表和复制链表拆分出来**,**并将原链表复原**:![](/media/202201/2022-01-09_2132480.08964373357277822.png) ## 3 参考代码 ```java /** * 138. 复制带随机指针的链表 * @param head 链表头结点 * @return 原链表的复制链表 */ public Node copyRandomList(Node head) { // 复制每个节点,并将原链表和复制链表连在一起 for (Node p = head; p != null; p = p.next.next) { Node q = new Node(p.val); q.next = p.next; p.next = q; } // 复制 random 指针 for (Node p = head; p != null; p = p.next.next) { if (p.random != null) { p.next.random = p.random.next; } } // 拆分两个链表,并复原原链表 Node dummy = new Node(-1), cur = dummy; for (Node p = head; p != null; p = p.next) { Node q = p.next; cur.next = q; cur = cur.next; p.next = q.next; } // 返回原链表的复制链表 return dummy.next; } ``` ## 参考文献 1. [138. 复制带随机指针的链表](https://leetcode-cn.com/problems/copy-list-with-random-pointer)。 2. [复制带随机指针的链表 | 图解迭代和哈希两种做法 【c++/java 版本】](https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/fu-zhi-dai-sui-ji-zhi-zhen-de-lian-biao-c2nvs)。
ricear
2022年6月26日 12:29
©
BY-NC-ND(4.0)
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码