题目

请实现 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。

思路1

我们利用HashMap,key存储旧的链表,value存储新的链表,先将链表复制一份到Map中,然后再同步遍历来设置他的next和random指针。最后返回复制的链表的head即可。

代码实现

class Solution {
public Node copyRandomList(Node head) {
HashMap<Node, Node> map = new HashMap<>();
//由于待会还要用到head,所以创建一个Node用指向head
Node cur = head;
//复制链表到HashMap中
while (cur != null) {
map.put(cur, new Node(cur.val));
cur = cur.next;
}
cur = head; while (cur != null) {
//设置next指向,将复制的链表连接起来
map.get(cur).next = map.get(cur.next);
//将复制的链表的random指向与原来链表同步
map.get(cur).random = map.get(cur.random);
cur = cur.next;
}
//获取map中head对应的value(即新链表)返回
return map.get(head); }
}

思路2

分三步来解决:

  1. 先将每个结点复制,然后跟在原来结点的后面,并且连接起来
  2. 设置复制的结点的random指向和原来的链表的random指向一样
  3. 将链表分离即可。

代码实现

class Solution {
public Node copyRandomList(Node head) {
copy(head);
randomDirect(head);
return getResult(head); } //第一步:先将每个结点复制,然后跟在原来结点的后面
public void copy(Node head) {
//复制每个结点到当前结点的下一个结点
while (head != null) {
//克隆当前结点
Node cloneNode = new Node(head.val);
//获取下一个要复制的结点
Node nextNode = head.next; //将复制的结点和原来的链表链接起来
head.next = cloneNode;
cloneNode.next = nextNode; //将head指向下一个要复制的结点
head = nextNode;
}
} //第二步:设置复制的结点的random指向和原来的链表的random指向一样
public void randomDirect(Node head) {
while (head != null) {
//获取原链表对应的复制的结点
Node cloneNode = head.next;
//如果是空的会就跳过,否则会触发空指针异常
if (head.random != null) {
Node direct = head.random;
//必须要用next才能指向我们复制的结点,如果没有加next那么就会指向原来的结点,不合题意
cloneNode.random = direct.next;
}
head = cloneNode.next;
}
} //第三步:将旧链表与新链表分离
public Node getResult(Node head) {
//如果输入的head为空,那么直接返回
if (head == null) {
return null;
}
//获取复制的链表的头结点
Node cloneNode = head.next;
Node cloneHead = head.next;
//将head的下一个结点修改为原来链表的下一个结点,然后再将head指向它
head.next = head.next.next;
head = head.next;
while (head != null) {
cloneNode.next = head.next;
cloneNode = cloneNode.next;
//由于原来的链表顺序也不能修改,所以两个链表必须全部分离,不能有依赖
head.next = head.next.next;
head = head.next;
}
return cloneHead;
}
}

力扣 - 剑指Offer 35.复杂链表的复制的更多相关文章

  1. 剑指 Offer 35. 复杂链表的复制

    剑指 Offer 35. 复杂链表的复制 Offer_35 题目详情 方法一 可以使用一个HashMap来存储旧结点和新结点的映射. 这种方法需要遍历链表两遍,因为需要首先知道映射关系才能求出next ...

  2. 【Java】 剑指offer(35) 复杂链表的复制

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 请实现函数ComplexListNode* Clone(Compl ...

  3. 剑指offer——35复杂链表的复制

    这题很是巧妙. 突破了常规思维. 竟然可以把传入进来的链表和复制的链表链在一起.然后再算出slibling指针.最后在分离. 直接把空间复杂度变为O(1)了. 很巧妙,很实用. 题目: 请实现函数Co ...

  4. 每日一题 - 剑指 Offer 35. 复杂链表的复制

    题目信息 时间: 2019-06-28 题目链接:Leetcode tag: 链表 难易程度:中等 题目描述: 请实现 copyRandomList 函数,复制一个复杂链表.在复杂链表中,每个节点除了 ...

  5. 【剑指Offer】复杂链表的复制 解题报告(Python)

    [剑指Offer]复杂链表的复制 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题 ...

  6. 《剑指offer》复杂链表的复制

    本题来自<剑指offer> 反转链表 题目: 思路: C++ Code: Python Code: 总结:

  7. 力扣 - 剑指 Offer 06. 从尾到头打印链表.md

    题目 剑指 Offer 06. 从尾到头打印链表 思路1(递归) 首先先遍历整个脸表,计算出链表的长度(用于初始化数组).然后进行递归,从链表头部递归到尾部,这期间什么都不做,直到递归到最后一个节点的 ...

  8. 力扣 - 剑指 Offer 22. 链表中倒数第k个节点

    题目 剑指 Offer 22. 链表中倒数第k个节点 思路1(栈) 既然要倒数第k个节点,那我们直接把所有节点放到栈(先进后出)里面,然后pop弹出k个元素就可以了 代码 class Solution ...

  9. 力扣 - 剑指 Offer 52. 两个链表的第一个公共节点

    题目 剑指 Offer 52. 两个链表的第一个公共节点 思路1(栈) 若两个链表相遇,则从它开始相遇的地方到链表末尾应该都是相同的,那么我们可以将两个链表分别放入两个栈中,然后依次循环比较两个栈顶的 ...

随机推荐

  1. 07 C语言常量

    常量的定义 常量是指固定的值,固定值在程序执行期间不会改变.这些固定值,又叫做字面量. 常量可以是任意的基本数据类型,比如整数常量.浮点常量.字符常量,或字符串字面值,也有枚举常量. 不要搞得太复杂, ...

  2. C++重载>>和<<(输入和输出运算符)详解

    转载:http://c.biancheng.net/view/2311.html 在C++中,标准库本身已经对左移运算符<<和右移运算符>>分别进行了重载,使其能够用于不同数据 ...

  3. Thymeleaf 异常:Exception processing template "index": An error happened during template parsing (template: "class path resource [templates/index.html]")

    Spring Boot 项目,在 Spring Tool Suite 4, Version: 4.4.0.RELEASE 运行没有问题,将项目中的静态资源和页面复制到 IDEA 的项目中,除了 IDE ...

  4. JVM 内存分配和占用

    我们从一个简单示例来引出JVM的内存模型 简单示例 我从一个简单示例谈起这一块,我在看一篇文章的时候看到这么一个场景并且自己做了尝试,就是分配一个2M的数组,使用Xmx即最大内存为12M的话,会报错J ...

  5. 初始python的类

    面向对象 一.面向对象 优点: 面向对象编程:是一类相似功能函数的集合,使你的代码更清晰化,更合理化. 面向对象,要拥有上帝的视角看问题,类其实就是一个公共模板,对象就从具体的模板实例化出来 类:就是 ...

  6. css实现中间横线俩边文字效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 多路复用select和epoll的区别(转)

    先说下本文框架,先是问题引出,然后概括两个机制的区别和联系,最后介绍每个接口的用法 一.问题引出 联系区别 问题的引出,当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一 ...

  8. Java 合并Word文档

    合并文档可以是将两个包含一定逻辑关系的文档合并成一个完整的文档,也可以是出于方便文档存储.管理的目的合并多个文档为一个文档.下面,就将以上文档操作需求,通过Java程序来实现Word文档合并.合并文档 ...

  9. pytest文档43-元数据使用(pytest-metadata)

    前言 什么是元数据?元数据是关于数据的描述,存储着关于数据的信息,为人们更方便地检索信息提供了帮助. pytest 框架里面的元数据可以使用 pytest-metadata 插件实现.文档地址http ...

  10. selenium原理学习笔记

    一,selenium工作原理(参考文档:https://blog.csdn.net/dawei_yang000000/article/details/87639928) 自动化测试代码发送请求给到浏览 ...