热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java详解剑指offer面试题35复杂链表的复制

Java详解剑指offer面试题35–复杂链表的复制输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,
Java详解剑指offer面试题35–复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

复杂链表的定义如下

private class RandomListNode {int label;RandomListNode next = null;RandomListNode random = null;RandomListNode(int label) {this.label = label;}
}

**注意不可将链表头结点引用返回,所以需要自己new一个结点出来。**要完成复杂链表的复制,第一步要完成普通链表的复制,普通链表的复制可以用一个栈复制每一个结点,之后逐个弹出并连接起来。对于本题有两种策略:

第一种是,在复制普通链表时,将原链表结点和复制链表的结点成对存入HashMap中,建立一对一的映射。当进行随机结点复制时,遍历原链表,如果某结点的随机结点不为空,那么根据HashMap能以O(1)的时间找到对应的复制链表结点中,若原始链表的结点M指向随机结点S,那么复制链表的M’也要指向结点S’,这种方法时间复杂度为O(N),但空间复杂度为O(N)。

更好的方法是,插入、连接、拆分三步法。

  • 插入:在原始链表的每个结点后插入一个值和它一样的新结点;则有oriNode.next == cloneNode这样的关系;
  • 连接随机结点:遍历插入新结点后的链表,在访问原始链表中的那些结点时,判断其是否有随机结点,有的话cloneNode.random = oriNode.random.next这里oriNode.random.next表示原始链表随机结点的下一个结点,其实就是复制链表的随机结点。
  • 拆分原始链表和复制链表:将奇数结点相连就是原始链表,将偶数结点相连就是我们想要的复制链表。返回复制链表的头结点即可。

package Chap4;/*** 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head* (注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)*/
public class CloneLinkedList {private class RandomListNode {int label;RandomListNode next = null;RandomListNode random = null;RandomListNode(int label) {this.label = label;}}/*** 1、为每个结点的next插入一个和该结点的值一样的结点* 2、设置每个复制结点的random结点* 3、将链表拆分,返回复制链表的头结点** @param pHead 原链表头结点* @return 复制链表的头结点,不可直接返回原链接结点的引用,必须使用new出来的RandomListNode*/public RandomListNode Clone(RandomListNode pHead) {if (pHead == null) return null;copyNode(pHead);setCloneRandomNode(pHead);return splitList(pHead);}// 1. 为每个结点的next插入一个和该结点的值一样的结点private void copyNode(RandomListNode head) {RandomListNode cur = head;while (cur != null) {RandomListNode cloneNode = new RandomListNode(cur.label);cloneNode.next = cur.next;cur.next = cloneNode;cur = cloneNode.next;}}// 2. 设置每个复制结点的randomprivate void setCloneRandomNode(RandomListNode head) {RandomListNode cur = head;while (cur != null) {RandomListNode cloneNode = cur.next;if (cur.random != null) {cloneNode.random = cur.random.next;}cur = cloneNode.next;}}// 3. 拆分链表private RandomListNode splitList(RandomListNode head) {RandomListNode cur = head;RandomListNode cloneHead = cur.next;while (cur != null) {RandomListNode cloneNode = cur.next;cur.next = cur.next.next;if (cloneNode.next != null) {cloneNode.next = cloneNode.next.next;}cur = cur.next;}return cloneHead;}
}

该方法没有用到额外的空间,仅仅是对每个结点进行插入、删除操作等。时间复杂度为O(N).


本文参考文献:
[1]github.com/haiyusun/data-structures


推荐阅读
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 浅析python实现布隆过滤器及Redis中的缓存穿透原理_python
    本文带你了解了位图的实现,布隆过滤器的原理及Python中的使用,以及布隆过滤器如何应对Redis中的缓存穿透,相信你对布隆过滤 ... [详细]
  • Spring Boot 中配置全局文件上传路径并实现文件上传功能
    本文介绍如何在 Spring Boot 项目中配置全局文件上传路径,并通过读取配置项实现文件上传功能。通过这种方式,可以更好地管理和维护文件路径。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • com.sun.javadoc.PackageDoc.exceptions()方法的使用及代码示例 ... [详细]
  • 如何使用 `org.eclipse.rdf4j.query.impl.MapBindingSet.getValue()` 方法及其代码示例详解 ... [详细]
  • 《我的世界》Java版种子合集:探索多样世界生成
    本文介绍了《我的世界》Java版中用于生成多样化游戏世界的种子代码。这些种子是由一个或多个字符(包括正整数和负整数)组成的值,能够为玩家带来截然不同的地形和环境体验。通过使用不同的种子,玩家可以探索各种独特的地貌、生物群系和结构,从而丰富游戏的乐趣和挑战性。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
  • 在Java项目中,当两个文件进行互相调用时出现了函数错误。具体问题出现在 `MainFrame.java` 文件中,该文件位于 `cn.javass.bookmgr` 包下,并且导入了 `java.awt.BorderLayout` 和 `java.awt.Event` 等相关类。为了确保项目的正常运行,请求提供专业的解决方案,以解决函数调用中的错误。建议从类路径、依赖关系和方法签名等方面入手,进行全面排查和调试。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 本题探讨如何编写程序来计算一个数值的整数次方,涉及多种情况的处理。 ... [详细]
  • 本文详细解析了客户端与服务器之间的交互过程,重点介绍了Socket通信机制。IP地址由32位的4个8位二进制数组成,分为网络地址和主机地址两部分。通过使用 `ipconfig /all` 命令,用户可以查看详细的IP配置信息。此外,文章还介绍了如何使用 `ping` 命令测试网络连通性,例如 `ping 127.0.0.1` 可以检测本机网络是否正常。这些技术细节对于理解网络通信的基本原理具有重要意义。 ... [详细]
  • 深入解析:Synchronized 关键字在 Java 中对 int 和 Integer 对象的作用与影响
    深入探讨了 `Synchronized` 关键字在 Java 中对 `int` 和 `Integer` 对象的影响。尽管初看此题似乎简单,但其实质在于理解对象的概念。根据《Java编程思想》第二章的观点,一切皆为对象。本文详细分析了 `Synchronized` 关键字在不同数据类型上的作用机制,特别是对基本数据类型 `int` 和包装类 `Integer` 的区别处理,帮助读者深入理解 Java 中的同步机制及其在多线程环境中的应用。 ... [详细]
  • 工作8年后薪资从1万跃升至7万,网友惊叹:本科学历实属难得
    一位本科毕业生在工作8年后,凭借扎实的技术能力和不断的学习提升,成功将月薪从1万元提高到7万元,引发了网友们的广泛赞叹。这一成就不仅体现了个人的努力与坚持,也反映了当前技术领域对高素质人才的迫切需求。 ... [详细]
author-avatar
功民昌
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有