OJ题:随机链表的复制—Java数据结构

目录

随机链表的复制

1. 完整题目

2.错误做法

3.第一次遍历 

1.拷贝所有旧节点的val域

 2. 串联老节点和新节点

3. 第一次遍历代码: 

4.第二次遍历

1. 表示出新链表的节点

2. 表示出新节点的next,random

3. 通过映射关系赋值next,random

4. 第二次遍历代码

5.设置返回值 

6.完整代码


 

随机链表的复制

随机链表的复制 - 力扣(LeetCode)

1. 完整题目

9152da6c854a4c329012d83c244c9d2a.png

eb19ba82b20b4c54b329b4c4e9fe4cbb.png

 进一步读题,获取更多信息:

我们通过进一步读题,可以得出每个节点的形式,每个节点有三个域:val域,next域,及random域。通过节点的形式,我们可以画出一条符合题意的链表。

这条链表入下图,val域存储着该节点存放的值;next域存放着下一个节点的地址

random域比较特殊;它可能存放着链表中,任意节点的地址,可以是指向自己,也可以指向不相邻的节点,甚至可以为null。也就是说,random域存放着链表中任意一个节点的指针或者为null

 2e507cbae8cf422784be28170d2ef2f6.png

我们要对这条链表进行深拷贝,就是将这条链表中所有节点的val域,及各个节点间域的指向关系,都以相同形式拷贝出一条新链表。


2.错误做法

对于该题,很多uu们的做法是:定义一个cur,用cur从当前链表的头节点开始,遍历链表,把遍历到的的节点的cur.val,cur.next,cur.random三个域,拷贝到新创建的链表中,直到cur遍历完完整的链表。

这种做法是错误的,为什么呢?

d053656a2b214142b6825f7340d69d7c.png

题目的意思是,让我们对原链表进行深拷贝。

对于图中的原链表,当前cur指向该链表的头节点,cur.next指向0x56这个节点,要把0x56拷贝一份,那拷贝出来的节点的地址可能是0x89。

这时候就出现问题了,按照这种做法,拷贝出的新的头节点的next域,指向的是原链表的第二个节点,而不是指向新链表的第二个节点。

2082aa8355b04893a9af0dbdd987dd56.png


3.第一次遍历 


1.拷贝所有旧节点的val域

对于该题,我们定义一个cur,遍历原链表的每一个节点。

cur从头节点开始向后遍历,只要cur不为null,就对应地实例化一个新的节点

实例化好新节点后,可以先不管新节点的next域和random域,把旧节点的val值拷贝到新节点

1b81dcfab94f4da9abcf07dc88286321.png


 2. 串联老节点和新节点

在拷贝所有旧节点的val域的同时,我们需要提前创建好一个HashMap类型的map,map中的每一个元素entry,key域用于存储旧节点的地址,val域用于存储新节点的地址通过map的特性,我们就把每一个老节点和对应的新节点串联起来:

291a8648ff5b43f38e114fd85770a1c2.png

当然,仅仅一次遍历,是完全不足以解决问题的,我们还要进行第二次遍历,题目中传入的形参head,指向原链表头节点。方便每次遍历时,cur都能直接找到原链表头节点:

b7c036d041aa42cf93dea4c8d77b5a77.png


3. 第一次遍历代码: 

aeaf3ddea66d48f184c321ec0bfd1cd4.png

4.第二次遍历


 第二次遍历,就是要通过刚刚串联旧节点和新节点的map,修改新节点的next域和random域


1. 表示出新链表的节点

113c16f623b046eaa0cab30fdb5720b0.png

对于新链表的节点地址,我们只要拿到了元素entry的key值,通过map,就可以通过get()方法,来获取到entry元素对应key的val值,entry.val==map.get(entry.key)。

194db00ee9e346129f9e249b5109f0bf.png


2. 表示出新节点的next,random

113c16f623b046eaa0cab30fdb5720b0.png

对于新节点的next域,可以表示为map.get(cur).next

同理,对于新节点的random域,可以表示为map.get(cur).random


3. 通过映射关系赋值next,random

就拿新旧节点的next域来举例,我们可以通过cur.next指向旧链表的下一个节点,那么如何通过串联新旧节点的map,来让新节点的next域,指向新链表中的下一个节点呢?

dfb2af478bc14eee9e966cc977738a9e.png

通过map.get(cur.next):

cur.next拿到了 原链表正在遍历的节点 的下一个节点 ;

map.get(~)拿到了 对应新链表的节点 的地址。 

通过map.get(cur).next:

map.get(cur)拿到了 原链表正在遍历的节点 对应新链表的节点;

 ~.next 拿到了 对应新链表的节点 的next域。 


 所以,令 map.get(cur).next = map.get(cur.next) 即可正确地修改新节点的next域,指向新链表的下一个节点。

修改新节点的random域同理,map.get(cur).random = map.get(cur.random).


4. 第二次遍历代码

a5efc1d93f0441e58f1d2c2578a3cec7.png


5.设置返回值 

8ca1277e69084b6f9dba28d52e5829c2.png


以上,就是随机链表复制的全部内容 !

896217ecfb924dd6bb3dd5e096ac4945.png


 6.完整代码

class Node{
        int val;
        Node next;
        Node random;
        public Node(int val) {
            this.val = val;
            this.next = null;
            this.random = null;
        }
    }
    public Node copyRandomList(Node head) {
        HashMap<Node,Node> map=new HashMap<>();
        Node cur=head;
        while (cur!=null){
            Node node=new Node(cur.val);
            map.put(cur,node);
            cur=cur.next;
        }

        cur=head;

        while (cur!=null){
            map.get(cur).next=map.get(cur.next);
            map.get(cur).random=map.get(cur.random);
            cur=cur.next;
        }
        return map.get(head);
    }
    public List<String> topKFrequent(String[] words , int k){
        HashMap<String,Integer> map=new HashMap<>();

        for (String word : words) {
            if (map.get(word)==null){
                map.put(word,1);
            } else {
                int val = map.get(word);
                map.put(word,val+1);
            }
        }

 

 

 

 

 

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

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

相关文章

DAY53WEB 攻防-XSS 跨站SVGPDFFlashMXSSUXSS配合上传文件添加脚本

知识点&#xff1a; 1、XSS跨站-MXSS&UXSS 2、XSS跨站-SVG制作&配合上传 3、XSS跨站-PDF制作&配合上传 4、XSS跨站-SWF制作&反编译&上传 XSS分类&#xff1a;https://www.fooying.com/the-art-of-xss-1-introduction/&#xff08;失效了&#xff09; …

案例实践 | 以长安链为坚实底层,江海链助力南通民政打造慈善应用标杆

案例名称-江海链 ■ 实施单位 中国移动通信集团江苏有限公司南通分公司、中国移动通信集团江苏有限公司 ■ 业主单位 江苏省南通市民政局 ■ 上线时间 2023年12月 ■ 用户群体 南通市民政局、南通慈善总会等慈善组织及全市民众 ■ 用户规模 全市近30家慈善组织&#…

【专题】计算机网络概述

1. 计算机网络的作用及其发展史 1.1. 计算机网络的作用 二十一世纪的一些重要特征就是数字化、网络化和信息化&#xff0c;它是一个以网络为核心的信息时代。 网络现在已经成为信息社会的命脉和发展知识经济的重要基础。 信息时代以网络为核心。 (1) 网络 “网络”是一个统称…

selenium:操作滚动条的方法(8)

selenium支持几种操作滚动条的方法&#xff0c;主要介绍如下&#xff1a; 使用ActionChains 类模拟鼠标滚轮操作 使用函数ActionChains.send_keys发送按键Keys.PAGE_DOWN往下滑动页面&#xff0c;发送按键Keys.PAGE_UP往上滑动页面。 from selenium import webdriver from se…

数学考研高分突破:解题思维与速度的双重修炼

随着考研季的临近&#xff0c;众多考生为了在数学这一科目中取得高分&#xff0c;纷纷投入到紧张的复习中&#xff0c;如何在有限的时间内&#xff0c;既提高解题思维&#xff0c;又提升解题速度&#xff0c;成为了许多考生心中的难题&#xff0c;本文将围绕这一主题&#xff0…

绘制YOLOv11模型在训练过程中,精准率,召回率,mAP_0.5,mAP_0.5:0.95,以及各种损失的变化曲线

一、本文介绍 本文用于绘制模型在训练过程中,精准率,召回率,mAP_0.5,mAP_0.5:0.95,以及各种损失的变化曲线。用以比较不同算法的收敛速度,最终精度等,并且能够在论文中直观的展示改进效果。支持多文件的数据比较。 专栏目录:YOLOv11改进目录一览 | 涉及卷积层、轻量化…

SpringMVC后台控制端校验-表单验证深度分析与实战优化

前言 在实战开发中&#xff0c;数据校验也是十分重要的环节之一&#xff0c;数据校验大体分为三部分&#xff1a; 前端校验后端校验数据库校验 本文讲解如何在后端控制端进行表单校验的工作 案例实现 在进行项目开发的时候,前端(jquery-validate),后端,数据库都要进行相关的数据…

【华为】静态路由配置

1.配置接入层&#xff1a; LSW1&#xff08;LSW3同理&#xff09;: vlan batch 10 20 in g0/0/1 port link-type ac port default vlan 10 in g0/0/2 port link-type ac port default vlan 20 in g0/0/24 port link-type tr port tr allow-pass vlan 10 202.配置汇聚层&#xf…

v853扬声器调试

文章目录 1、前言2、环境介绍3、修改设备树4、使用tinymix测试扬声器 1、前言 本文记录v853下的扬声器调试。 2、环境介绍 硬件&#xff1a;韦东山v853 aicit板卡 软件&#xff1a;v853 tina sdk 3、修改设备树 扬声器使用的是v853内置的audio codec&#xff0c;原理图如…

进程的属性

一、进程状态 CPU执行进程代码不是把进程代码执行完毕&#xff0c;才开始执行下一个&#xff0c;而是给每一个进程预分配一个时间片&#xff0c;基于时间片&#xff0c;进行调度轮转。 并行和并发 并行: 多个进程在多个CPU下分别&#xff0c;同时进行运行&#xff0c;这称之…

设计小白必看!一文教你区分原型图和UI图

产品设计过程中&#xff0c;产品经理或UI设计师常常需要在不同的设计阶段产出不同的原型图和UI图。初入职场的产品小白或UI小白很容易将原型图和UI图混淆&#xff0c;不能完全区分它们各自的作用&#xff0c;从而影响了设计流程的效率和效果。本文将详细解析原型图与UI图的定义…

【DS】哈希表,哈希桶的实现

目录 哈希概念哈希冲突哈希函数负载因子哈希冲突的解决闭散列开散列 哈希表闭散列的实现哈希表的结构哈希函数构造函数查找插入删除 哈希表开散列的实现哈希表的结构查找插入删除 哈希表的表长建议是素数 平衡二叉树的学习中&#xff0c;学习及模拟实现了AVL树和红黑树&#xf…

uni-app写的微信小程序如何体积太大如何处理

方法一&#xff1a;对主包进行分包处理&#xff0c;将使用url: /pages/components/equipment/equipment跳转页面的全部拆分为分包&#xff0c;如url: /pagesS/components/equipment/equipment 在pages.json中添加 "subPackages": [{ "root"…

STM32项目实战:基于STM32F4的智能灯光控制系统(LVGL),附项目教程/源码

《智能灯光控制系统_STM32F4》项目完整文档、项目源码&#xff0c;点击下方链接免费领取。 项目资料领取https://s.c1ns.cn/jjQK7 STM32项目实战之“智能灯光控制系统”&#xff08;基于STM32F4&#xff09; 今天小编来分享一个《智能灯光控制系统》的项目案例&#xff0c;硬件…

如何批量下载采集淘宝图片?3个方法可以帮助你

如何批量下载采集淘宝图片&#xff1f;在现代电子商务的背景下&#xff0c;淘宝作为中国最大的在线购物平台之一&#xff0c;承载了数以亿计的商品和信息。对于从事电商运营、市场推广或网络营销的人员而言&#xff0c;采集淘宝图片已经成为日常工作中的重要任务。这不仅是为了…

Jenkins pipeline语法笔记

Jenkins pipeline 简介Jenkins Pipeline 优势DSL 是什么 pipeline支持两种语法&#xff1a;声明式pipeline语法&#xff1a;Pipelineagent Pipeline 声明式语法DeclarativeenvironmentoptionsparameterstriggerstoolsinputwhenParallel Pipeline Scripted语法创建一个简单的 Pi…

(38)MATLAB分析带噪信号的频谱

文章目录 前言一、MATLAB仿真代码二、仿真结果画图总结 前言 本文给出带噪信号的时域和频域分析&#xff0c;指出频域分析在处理带噪信号时的优势。 首先使用MATLAB生成一段信号&#xff0c;并在信号上叠加高斯白噪声得到带噪信号&#xff0c;然后对带噪信号对其进行FFT变换&…

数据结构:跳表

数据结构&#xff1a;跳表 跳表实现类架构构造函数析构函数查找插入删除 总代码 跳表 在传统的链表中&#xff0c;不论单链表还是双链表&#xff0c;查询时都要O(N)的时间复杂度&#xff0c;就算是一个有序链表&#xff0c;由于无法像数组一样定址&#xff0c;无法进行二分查找…

学习最新vue20.17.0-事件处理

vue中文官网事件处理 | Vue.js (vuejs.org) 我在官网基础上,添加些代码,方便初学者学习,能够快速理解官网内容,掌握自己所需要的知识,以便节省宝贵的时间。 事件处理 监听事件 我们可以使用 v-on 指令 (简写为 @) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript…

Anaconda3与PyCharm安装配置

参考文章 Anaconda3与PyCharm安装配置保姆教程 参照上面文章&#xff0c;安装好Anaconda3和PyCharm环境 下面重点记录下环境配置 1&#xff0c;在window系统菜单中选择Anaconda Prompt&#xff0c;而不是Anaconda Powershell Prompt 2, 打开Anaconda Prompt&#xff0c;输…