【三次优化】剑指 Offer 35. 复杂链表的复制
立志用最少代码做最高效的表达
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 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。提示:
-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。
思路一:HashMap
思路:以map将新节点和旧节点映射起来,进而建立链表。
步骤:
1、完成以next指针为串联的链表的建立,并建立HashMap映射
2、完成random的链表建设
缺点:冗余
class Solution {public Node copyRandomList(Node head) {/**1、根据next完成链表的复制,同时建立hash表映射2、根据hash表的映射进行random的指向*/if(head == null) return null; //头结点为空的情况Map<Node, Node> map = new HashMap<>(); // 建立Map映射,映射原节点和被复制的节点Node copyListHead = new Node(head.val); // 复制链表的头结点map.put(head, copyListHead); // 建立头结点间的映射Node oldTmpList1 = head.next; // 原链表的临时遍历节点Node copyTmpList1 = copyListHead; // 复制链表的临时遍历节点1// 1、完成next的复制while(oldTmpList1 != null) {Node newTmpList1 = new Node(oldTmpList1.val); // 赋值链表的临时遍历节点2(因为建表需要两个节点)map.put(oldTmpList1, newTmpList1); // 建立映射copyTmpList1.next = newTmpList1; // 建表过程copyTmpList1 = newTmpList1;oldTmpList1 = oldTmpList1.next;}// 2、完成random的复制Node oldTmpList2 = head;Node newTmpList2 = copyListHead; // 复制链表的临时遍历节点1while(oldTmpList2 != null) {if(oldTmpList2.random != null) {newTmpList2.random = map.get(oldTmpList2.random);}oldTmpList2 = oldTmpList2.next;newTmpList2 = newTmpList2.next;}return copyListHead;}
}
思路2:对思路1的优化
拆分成两步:
1、将新旧节点映射起来
2、进行next和random的链表建立
时间复杂度:O(n) 、 空间复杂度:O(n)
class Solution {public Node copyRandomList(Node head) {if(head == null) return null; //头结点为空的情况Map<Node, Node>map = new HashMap<>(); // 建立Map映射,映射原节点和被复制的节点Node copyListHead = new Node(head.val); // 复制链表的头结点// 1、进行Map映射for(Node tmp = head; tmp != null; tmp = tmp.next) {if(tmp == head) map.put(head, copyListHead); // 头结点单独判断else map.put(tmp, new Node(tmp.val)); // 建立映射}// 2、完成next的复制和random的复制for(Node tmp = head; tmp != null; tmp = tmp.next) {map.get(tmp).next = map.get(tmp.next);map.get(tmp).random = map.get(tmp.random);}return copyListHead;}
}
代码3:原地复制
思路:在原链表的每个节点后都构建一个新节点,将原来形如A->B->C
的链表改为A->A'->B->B'->C->C'
,然后拆分两链表即可。
步骤:
1、复制各个节点,构建拼接链表
2、构建各个新节点的random指针
3、拆分成两个链表
注意:本题的题意是深拷贝,即不能更改原链表。
class Solution {public Node copyRandomList(Node head) {if(head == null) return null;Node cur = head;// 1. 复制各节点,并构建拼接链表while(cur != null) {Node tmp = new Node(cur.val);tmp.next = cur.next;cur.next = tmp;cur = tmp.next;}// 2. 构建各新节点的 random 指向cur = head;while(cur != null) {if(cur.random != null)cur.next.random = cur.random.next;cur = cur.next.next;}// 3. 拆分两链表cur = head.next;Node pre = head, res = head.next;while(cur.next != null) {pre.next = pre.next.next;cur.next = cur.next.next;pre = pre.next;cur = cur.next;}pre.next = null; // 单独处理原链表尾节点return res; // 返回新链表头节点}
}
【三次优化】剑指 Offer 35. 复杂链表的复制相关推荐
- 剑指 Offer 35. 复杂链表的复制
剑指 Offer 35. 复杂链表的复制 题目 题目链接 解题思路 题目理解 解题思路 具体代码 题目 题目链接 https://leetcode-cn.com/problems/fu-za-lian ...
- 【LeetCode】剑指 Offer 35. 复杂链表的复制
[LeetCode]剑指 Offer 35. 复杂链表的复制 文章目录 [LeetCode]剑指 Offer 35. 复杂链表的复制 package offer;import java.util.Ar ...
- 剑指offer——35复杂链表的复制
这题很是巧妙. 突破了常规思维. 竟然可以把传入进来的链表和复制的链表链在一起.然后再算出slibling指针.最后在分离. 直接把空间复杂度变为O(1)了. 很巧妙,很实用. 题目: 请实现函数Co ...
- 剑指 Offer 35. 复杂链表的复制(哈希/衍生拆分图解)
题目描述 请实现 copyRandomList 函数,复制一个复杂链表.在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null. ...
- LeetCode笔记】剑指 Offer 35. 复杂链表的复制(Java、哈希表、原地算法)
文章目录 题目描述 思路 && 代码 1. 哈希表法 2. 原地算法 二刷 题目描述 主要有两个考虑点: 不能改变原链表 新链表赋予 next.random 时,复制结点不一定存在 思 ...
- 【算法】剑指 Offer 35. 复杂链表的复制 【重刷】
1.概述 地址:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/ 请实现 copyRandomList 函数,复制一个复 ...
- leetcode 剑指 Offer 35. 复杂链表的复制
题意 将一个链表复制一遍后输出,这个链表除了next指针外,还有一个random指针,随机指向链表中的节点(包括自身或者NULL). 解法 生成一个新的链表,然后根据新老链表同时循环遍历,找到当前老链 ...
- 【LeetCode 剑指 Offer 35. 复杂链表的复制(中等)】
题目: 请实现 copyRandomList 函数,复制一个复杂链表.在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null. ...
- 《剑指offer》-- 复杂链表的复制、字符串的排列、数组中出现次数超过一半的数字、连续子数组的最大和
一.复杂链表的复制: 参考牛客网的chancy:https://www.nowcoder.com/questionTerminal/f836b2c43afc4b35ad6adc41ec941dba 1 ...
最新文章
- Spring MVC前后端的数据传输
- 区域链实践第一步——区域链测试环境搭建
- 解决Debian安装后中文乱码
- CentOS 7 安装nexus
- mysql事物及事物等级_MySQL事物原理及事务隔离级别
- DataGrid实现简单的行分组
- python正则替换查询_使用Python中的正则表达式进行搜索和替换
- python re模块安装_python re模块
- python 重定向到其他cmd_python 如何重定向到另一个终端?
- angularjs 服务详解
- 三目运算符?:结合性
- 二维码内容过多,生成的二维码太复杂,导致扫码的时候,过慢或者扫不出来解决方案。附二维码生成、解析工具类
- MFC:Ribbon界面设计
- 数电基础知识——原码、反码、补码
- 一线二线城市工作的区别
- 仿真动画是怎么制作的? 仿真动画类型有哪些?
- excel合并两列内容_技巧不求人169期 Excel打印最常用的8大技巧 Excel合并多表数据...
- 《花花公子》刊登1985年乔布斯专访
- php后端开发需要懂什么意思,PHP中的=什么意思?_后端开发
- CVPR 2021 | “以音动人”:姿态可控的语音驱动说话人脸