当前位置:网站首页>[Interview high-frequency questions] Linked list high-frequency questions that can be gradually optimized
[Interview high-frequency questions] Linked list high-frequency questions that can be gradually optimized
2022-08-09 11:45:00 【Water palace trifoliate brush diary】
题目描述
这是 LeetCode 上的 「138. 复制带随机指针的链表」 ,难度为 「中等」.
Tag : 「哈希表」、「链表」
给你一个长度为 n
的链表,每个节点包含一个额外增加的随机指针 random
,该指针可以指向链表中的任何节点或空节点.
构造这个链表的 深拷贝. 深拷贝应该正好由 n
个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值.新节点的 next
指针和 random
指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态.复制链表中的指针都不应指向原链表中的节点 .
例如,如果原链表中有 X
和 Y
两个节点,其中 X.random --> Y
.那么在复制链表中对应的两个节点 x
和 y
,同样有 x.random --> y
.
返回复制链表的头节点.
用一个由 n
个节点组成的链表来表示输入/输出中的链表.每个节点用一个 [val, random_index]
表示:
val
:一个表示Node.val
的整数.random_index
:随机指针指向的节点索引(范围从 到 );如果不指向任何节点,则为null
.
你的代码 只 接受原链表的头节点 head
作为传入参数.
示例 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.
提示:
模拟 + 哈希表
如果不考虑 random
指针的话,对一条链表进行拷贝,我们只需要使用两个指针:一个用于遍历原链表,一个用于构造新链表(始终指向新链表的尾部)即可.这一步操作可看做是「创建节点 + 构建 next
指针关系」.
现在在此基础上增加一个 random
指针,我们可以将 next
指针和 random
指针关系的构建拆开进行:
先不考虑 random
指针,和原本的链表复制一样,创建新新节点,并构造next
指针关系,同时使用「哈希表」记录原节点和新节点的映射关系;对原链表和新链表进行同时遍历,对于原链表的每个节点上的 random
都通过「哈希表」找到对应的新random
节点,并在新链表上构造random
关系.
代码:
class Solution {
public Node copyRandomList(Node head) {
Node t = head;
Node dummy = new Node(-10010), cur = dummy;
Map<Node, Node> map = new HashMap<>();
while (head != null) {
Node node = new Node(head.val);
map.put(head, node);
cur.next = node;
cur = cur.next; head = head.next;
}
cur = dummy.next; head = t;
while (head != null) {
cur.random = map.get(head.random);
cur = cur.next; head = head.next;
}
return dummy.next;
}
}
时间复杂度: 空间复杂度:
模拟(原地算法)
显然时间复杂度上无法优化,考虑如何降低空间(不使用「哈希表」).
我们使用「哈希表」的目的为了实现原节点和新节点的映射关系,更进一步的是为了快速找到某个节点 random
在新链表的位置.
那么我们可以利用原链表的 next
做一个临时中转,从而实现映射.
具体的,我们可以按照如下流程进行:
对原链表的每个节点节点进行复制,并追加到原节点的后面; 完成 操作之后,链表的奇数位置代表了原链表节点,链表的偶数位置代表了新链表节点,且每个原节点的 next
指针执行了对应的新节点.这时候,我们需要构造新链表的random
指针关系,可以利用link[i + 1].random = link[i].random.next
, 为奇数下标,含义为 「新链表节点的random
指针指向旧链表对应节点的random
指针的下一个值」;对链表进行拆分操作.

代码:
class Solution {
public Node copyRandomList(Node head) {
if (head == null) return head;
Node t = head;
while (head != null) {
Node node = new Node(head.val);
node.next = head.next;
head.next = node;
head = node.next;
}
head = t;
while (head != null) {
if (head.random != null) head.next.random = head.random.next;
head = head.next.next;
}
head = t;
Node ans = head.next;
while (head != null) {
Node ne = head.next;
if (ne != null) head.next = ne.next;
head = ne;
}
return ans;
}
}
时间复杂度: 空间复杂度:
最后
这是我们「刷穿 LeetCode」系列文章的第 No.138
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完.
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码.如果涉及通解还会相应的代码模板.
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode .
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解.
更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地
边栏推荐
- C语言中信号函数(signal)的使用
- electron 应用开发优秀实践
- Open3D point cloud average point spacing evaluation
- 字符串 | 反转字符串 | 双指针法 | leecode刷题笔记
- _main C:/ti/ccs1011/ccs/tools/compiler/ti-cgt-c2000_20.2.1.LTS/lib/rts2800_fpu32.lib<ar在线升级跳转疑问
- ACM longest non-descent subsequence problem
- 研发需求的验收标准应该怎么写? | 敏捷实践
- Notepad++安装插件
- 二重指针-char **、int **的作用
- 百钱买鸡(一)
猜你喜欢
字节秋招二面把我干懵了,问我SYN报文什么情况下会被丢弃?
C# async 和 await 理解
【面试高频题】可逐步优化的链表高频题
BISS绝对值编码器_TI方案_线路延迟补偿
ICML 2022 | Out-of-Distribution Detection with Deep Nearest Neighbors
实现strcat函数
PTA 实验7-5 输出大写英文字母(10 分)
TI的片上固化好的boot ROM(上电引导加载程序)退出后的去向
人体解析(Human Parse)开源数据集整理
x86 exception handling and interrupt mechanism (2) interrupt vector table
随机推荐
学生成绩查找系统
x86 Exception Handling and Interrupt Mechanism (3) Interrupt Handling Process
ClickHouse物化视图(八)
推荐一个免费50时长的AI算力平台
PAT1005
Installation of gdb 10.2
Number theory knowledge
VS Code有趣插件
ICML 2022 | Out-of-Distribution Detection with Deep Nearest Neighbors
PAT1014 未解决
TIC2000系列处理器在线升级
mysql参数配置学习----临时表内存表的设置
Use gdb to debug multi-process programs, debug parent and child processes at the same time
BISS绝对值编码器_TI方案_线路延迟补偿
Double pointer - the role of char **, int **
拍频造成的轻微震荡
[现代控制理论]6_稳定性_李雅普诺夫_Lyapunov
OC-块对象
论文分享 | ACL2022 | 基于迁移学习的论元关系提取
Open3D point cloud average point spacing evaluation