【LeetCode-中等题】138. 复制带随机指针的链表

文章目录

    • 题目
    • 解题核心思路:找random指针指向
      • 思路一:哈希
      • 思路二:迭代构造新链表
    • 方法一:哈希+递归
    • 方法二:纯哈希
    • 方法三:迭代 + 节点拆分

题目

在这里插入图片描述

解题核心思路:找random指针指向

这里的拷贝属于深拷贝,就是不光是拷贝值,还要拷贝其指针的引用情况。如果只是单独的单向链表,则直接可以根据next指向找到下一个结点,然后创建一个新节点复制过来,直接拷贝,但是题目中的random指针指向的节点是没有归类的,这样我们就不可能使用普通的循环来进行拷贝,因为在拷贝的时候,你只能找到next,但是random并不知道,可能拷贝的同时random都还没创建出来

思路一:哈希

此题的复制,不单单要复制本身的.val值,还要把其next和random指向给复制过来。
那么我们可以借助一个哈希表Map来记录下旧链表的映射关系,key为旧链表的节点(包含next和random指向),value为新建的新节点(val值直接copy旧链表的节点)

1.

  1. 建立哈希表,key为旧链表的节点,value为新建的新节点
  2. 然后去循环链表的同时,根据key取出新节点,并且(依据旧节点)设置新节点的next和random
  3. 最后返回新链表的首节点map.get(head);
    在这里插入图片描述

这里可以用纯哈希+while或者 哈希+递归的方法,原理都是一样的

思路二:迭代构造新链表

给每个旧链表节点后面都连上一个自己的复制节点,然后再根据老节点的random给后面的新节点附上,最后在把就新链表拆出来

  1. 构建新老链表结合体
    在这里插入图片描述

  2. 更新新节点的random
    在这里插入图片描述

  3. 拆链
    在这里插入图片描述

方法一:哈希+递归

 方法一 : 递归+哈希---->用哈希表记录旧值和新值的映射,让新值根据旧值的连接关系,构建新链表
    Map<Node, Node> map = new HashMap<Node, Node>();
    public Node copyRandomList(Node head) {
        if(head==null) return null;

        if(!map.containsKey(head)){//如果map集合不含head  则创建一份新的head进去  
         Node newHead = new Node(head.val);
         map.put(head,newHead);//key--->旧值  value--->新值   
         //给新值附上 next 和random
         newHead.next = copyRandomList(head.next);
         newHead.random = copyRandomList(head.random);
        }
        return map.get(head);
    }

方法二:纯哈希

方法二: 纯哈希----->  使用hash存储原结点和克隆结点的映射关系,通过映射关系处理克隆结点的random指针
    public Node copyRandomList(Node head) {
        if(head==null) return head;

        // map方法,空间复杂度O(n)
        Node oldNode = head;
       // 使用hash表存储旧结点和新结点的映射
        Map<Node,Node> map = new HashMap<>();
        while(oldNode != null){
            Node newNode = new Node(oldNode.val);
            map.put(oldNode,newNode);
            oldNode = oldNode.next;
        }

        oldNode = head;//重置 oldNode 位置到head头结点
        while(oldNode != null){ //根据旧node 映射新node
        map.get(oldNode).next = map.get(oldNode.next);
        map.get(oldNode).random = map.get(oldNode.random);
        oldNode = oldNode.next;
        }
        return map.get(head);//返回头结点的映射新节点
    }

方法三:迭代 + 节点拆分

/ 方法三: 迭代 + 节点拆分---->  给每一个旧的链表节点去拼接一个新的到旧节点后面,然后将新结点的random指向旧节点的random指向,最后再把新的节点拆分出来
public Node copyRandomList(Node head) {
        if (head == null) {
            return null;
        }
        // for (Node node = head; node != null; node = node.next.next) {
        //     Node nodeNew = new Node(node.val);
        //     nodeNew.next = node.next;
        //     node.next = nodeNew;
        // }
        // 第一次遍历,拼接新旧链表 旧1-->新1-->旧2--->新2
        Node node = head;
        while(node != null){
             Node nodeNew = new Node(node.val);
             nodeNew.next = node.next;
             node.next = nodeNew;
             node = node.next.next;
        }
        // for (Node node = head; node != null; node = node.next.next) {
        //     Node nodeNew = node.next;
        //     if(node.random != null) nodeNew.random = node.random.next;
        //     else nodeNew.random = null;
        // }
        // 第二次遍历,给新结点连上旧节点的random
         node = head;// 重置node到head位置
        while(node != null){
            Node nodeNew = node.next;
            if(node.random != null) nodeNew.random = node.random.next; 
            //如果旧节点的random指向null  null本身没有新节点,则直接让新节点的random指向null
            else nodeNew.random = null;
            node = node.next.next;
        }

        Node headNew = head.next;
        // for (Node node = head; node != null; node = node.next) {
        //     Node nodeNew = node.next;
        //     node.next = node.next.next;
        //     if(nodeNew.next != null) nodeNew.next = nodeNew.next.next;
        //     else nodeNew.next = null;
        // }
        node = head;// 重置node到head位置
        // 第三次遍历,拆分新链表出来
        while(node != null){
            Node nodeNew = node.next;
            node.next = nodeNew.next;
            if(nodeNew.next != null) nodeNew.next = nodeNew.next.next;
            else nodeNew.next = null;//防止最后一个新链表nodeNew.next.next出现空指针
            node = node.next;
        }
        return headNew;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/97770.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么曾经一马当先的C语言,如今却开始出现骂声

今日话题&#xff0c;为什么曾经一马当先的C语言&#xff0c;如今却开始出现各种骂声&#xff1f;C语言的发展历程可以追溯到20世纪70年代初期&#xff0c;它的设计理念、简洁性、可移植性以及对底层硬件的直接控制能力使其在计算机科学领域逐渐受到重视从而成为了天王搬到存在…

安捷伦DSA91204A高性能示波器/Agilent DSA91204A

描述 安捷伦的DSA90000A系列示波器为同等的DSO90000A产品增加了串行数据分析、EZJIT和50 M存储标准。 Infiniium DSO90000系列拥有业界领先的技术&#xff0c;能够提供超越规格的卓越示波器性能。加速测量任务的定制软件可以完全集成到示波器应用中&#xff0c;实现无缝操作。…

搭建Ubuntu本地web小游戏网站并通过内网穿透实现公网用户远程访问的步骤指南

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《高效编程技巧》《cpolar》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar内网穿透3.2 创建隧道3.3 测试公网访…

大数据(六):Pandas的基础应用详解(三)

专栏介绍 结合自身经验和内部资料总结的Python教程&#xff0c;每天3-5章&#xff0c;最短1个月就能全方位的完成Python的学习并进行实战开发&#xff0c;学完了定能成为大佬&#xff01;加油吧&#xff01;卷起来&#xff01; 全部文章请访问专栏&#xff1a;《Python全栈教…

下岗吧,Excel

ChatGPT的诞生使Excel公式变得过时。通过使用 ChatGPT 的代码解释器你可以做到&#xff1a; 分析数据创建图表 这就像用自然语言与电子表格交谈一样。我将向大家展示如何使用 ChatGPT 执行此操作并将结果导出为Excel格式&#xff1a; 作为示例&#xff0c;我将分析并创建美国…

用最少数量的箭引爆气球【贪心算法】

用最少数量的箭引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着 x 轴从不同点 完全垂直 地…

JVM ZGC垃圾收集器

ZGC垃圾收集器 ZGC&#xff08;“Z”并非什么专业名词的缩写&#xff0c;这款收集器的名字就叫作Z Garbage Collector&#xff09;是一款在JDK 11中新加入的具有实验性质[1]的低延迟垃圾收集器&#xff0c;是由Oracle公司研发的。 ZGC收集器是一款基于Region内存布局的&#…

vue 入门案例模版

vue 入门案例1 01.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> &l…

如何用Python爬虫持续监控商品价格

目录 持续监控商品价格步骤 1. 选择合适的爬虫库&#xff1a; 2. 选择目标网站&#xff1a; 3. 编写爬虫代码&#xff1a; 4. 设定监控频率&#xff1a; 5. 存储和展示数据&#xff1a; 6. 设置报警机制&#xff1a; 7. 异常处理和稳定性考虑&#xff1a; 可能会遇到的…

HBuilderX修改manifest.json设置,解决跨域问题(CORS、Cross-Origin)

搭建一个前台uniapp&#xff0c;后台springboot的开发环境时&#xff0c;遇到了跨域问题。 console提示错误信息&#xff1a; Access to XMLHttpRequest at http://10.0.180.203/api/cms/getAdList?apId1 from origin http://localhost:8080 has been blocked by CORS policy…

【实战】十一、看板页面及任务组页面开发(六) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十八)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…

关于Echarts 绘制玫瑰图 (笔记)

目录 基于js文件绘图 基于vue3绘制玫瑰图 基于js文件绘图 // 定义一个配置对象 var option {// 图例设置legend: {top: bottom},// 工具栏设置toolbox: {show: true,feature: {mark: { show: true }, // 标记工具dataView: { show: true, readOnly: false }, // 数据视图工具r…

煤矿皮带运输智能监控算法 opencv

煤矿皮带运输智能监控算法通过opencvpython深度学习算法网络模型&#xff0c;煤矿皮带运输智能监控算法实时监测皮带运输过程中的各种异常情况&#xff0c;如跑偏、撕裂、堆料异常等&#xff0c;一旦检测到异常情况&#xff0c;立即发出告警并采取相应的措施&#xff0c;以保障…

Windows系统中Apache Http服务器简单使用

1 简介 Apache HTTP服务器是一个开源的、跨平台的Web服务器软件。它由Apache软件基金会开发和维护。Apache HTTP服务器可以在多种操作系统上运行&#xff0c;如Windows、Linux、Unix等&#xff0c;并且支持多种编程语言和技术&#xff0c;如PHP、Perl、Python、Java等。…

机器学习基础16-建立预测模型项目模板

机器学习是一项经验技能&#xff0c;经验越多越好。在项目建立的过程中&#xff0c;实 践是掌握机器学习的最佳手段。在实践过程中&#xff0c;通过实际操作加深对分类和回归问题的每一个步骤的理解&#xff0c;达到学习机器学习的目的 预测模型项目模板 不能只通过阅读来掌握…

【遮天】李小曼回归,新形象无差云曦,短板竟是身材?

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析遮天 最新一集《遮天》已经更新&#xff0c;在成功卖掉段德之后&#xff0c;叶凡便离开妖帝坟冢&#xff0c;毕竟他身上拥有庞博从妖帝坟冢带出来的道经和被誉为中州至宝的绿铜 虽然这两样物品都在叶凡的苦海中&#xff0…

uniapp 开发之仿抖音,上下滑动切换视频、点击小爱心效果

效果图&#xff1a; 功能描述&#xff1a; 上下滑动视频&#xff0c;双击暂停&#xff0c;然后第一个视频再往上滑显示”已经滑到顶了“ 开始代码&#xff1a; 首先视频接口使用的公开的视频测试接口 开放API-2.0 官网展示 Swagger UI 接口文档 一…

AMEYA360:ROHM开发出适用于条码标签打印应用、超快打印速度的热敏打印头

AMEYA360&#xff1a;ROHM开发出适用于条码标签打印应用、超快打印速度的热敏打印头 全球知名半导体制造商ROHM(总部位于日本京都市)新推出两款高可靠性高速热敏打印头 “TE2004-QP1W00A(203dpi)”和“TE3004-TP1W00A(300dpi)”&#xff0c;新产品非常适用于物流和库存管理等领…

【Python自学笔记】Python好用的模块收集(持续更新...)

文章目录 日志模块钉钉机器人命令助手持续更新中,如果您有其他实用好用的模块欢迎留言...日志模块 写代码离不开日志,自定义一个理想的日志对于小白来说可能是一件很反锁的事情,就像我刚学习Python的时候自己写的一个自定义日志,为了解决这个痛点,今天就和大家分享一个可以…

Python 接口测试之接口关键字封装

引言 我们使用RF做UI自动化测试的时候&#xff0c;使用的是关键字驱动。同样&#xff0c;Python做接口自动化测试的时候&#xff0c;也可以使用关键字驱动。但是这里并不是叫关键字驱动&#xff0c;而是叫数据驱动。而接口测试的关键字是什么呢&#xff1f; 我们数据驱动的载体…