32 随机链表的复制

news2024/11/18 5:49:27

随机链表的复制

    • 题解1 哈希表
    • 题解2 回溯+哈希
      • 哈希思路精简
    • 题解3 优化迭代

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

例如,如果原链表中有 XY 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 xy ,同样有 x.random --> y

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null
你的代码 只 接受原链表的头节点 head 作为传入参数。
在这里插入图片描述
提示:

  • 0 <= n <= 1000
  • − 1 0 4 -10^4 104 <= Node.val <= 1 0 4 10^4 104
    Node.randomnull 或指向链表中的节点。
    注意:本题与主站 138 题相同:138

题解1 哈希表

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution {
public:

    Node* copyRandomList(Node* head) {
        if(! head) return nullptr;
        Node *p, *q, *f, *cphead;
        f = p = q = new Node(head->val);
        cphead = head;
		/** 受判题启发:给结点编号(array-like)
		    1. 变量需要3个map,分别记录结点-编号,编号-地址/结点,结点编号-其随机结点编号
		    2. 关键问题是:随机结点是在整个链表的基础上去看,即next建立了一条完整的链表,之后才有random的关系,即random结点是已经存在的结点,不能再new了
		**/
        unordered_map<Node*, int> idxmap;
        unordered_map<int, Node*> addrmap;
        unordered_map<int, int> randomidxmap;
      
        /** 对空特殊处理(可以让idx从1开始,避开0)
        int idx = 0;

        idxmap[nullptr] = 1001;
        randomidxmap[idxmap[nullptr]] = idxmap[nullptr];
        addrmap[randomidxmap[idxmap[nullptr]]] = nullptr;
        **/
        int idx = 1;
		// 结点编号,建立新链表
        while(head){
            idxmap[head] = idx;
            idxmap[q] = idx;
            addrmap[idx] = q;

            head = head->next;
            if(head)
                q->next = new Node(head->val);
            else q->next = nullptr;
            
            q = q->next;
            idx ++;
        }
		// 记录原链表的random关系
        while(cphead){
            randomidxmap[idxmap[cphead]] = idxmap[cphead->random];
            cphead = cphead->next;
        }
        // 复刻
        while(p){
            p->random = addrmap[randomidxmap[idxmap[p]]];
            p = p->next;
        }

        return f;
    }
};

在这里插入图片描述

题解2 回溯+哈希

class Solution {
public:
    // key = 原结点
    // value = 新结点
    unordered_map<Node*, Node*> Nodemap;
    Node* copyRandomList(Node* head) {
        if(! head) return nullptr;
        // 需要克服的问题是:不知道random指向的结点是否建立过	
        // 如果没建立过,则新建
        if(! Nodemap.count(head)){
            Node* newnode = new Node(head->val);
            Nodemap[head] = newnode;
            newnode->next = copyRandomList(head->next);
            newnode->random = copyRandomList(head->random); 
        }
        
        // 建立过直接返回
        return Nodemap[head];
    }
};

在这里插入图片描述

哈希思路精简

class Solution {
public:
   
    Node* copyRandomList(Node* head) {
        if(! head) return nullptr;
        map<Node*, Node*> kkmap;
        Node* autohead = head;
        
        // 新建链表
        // kkmap保证每个结点对应的都是新地址
        while(autohead){
            kkmap[autohead] = new Node(autohead->val);
            autohead = autohead->next;
        }
        autohead = head;
        
        // 建立next和random关系
        while(autohead){
            kkmap[autohead]->next = kkmap[autohead->next];
            kkmap[autohead]->random = kkmap[autohead->random];
            autohead = autohead->next;
        }


        return kkmap[head];
    }
};

在这里插入图片描述

题解3 优化迭代

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
   
    Node* copyRandomList(Node* head) {
        if(! head) return nullptr;
        Node* ll = head;
        Node* newhead;
        // copy to the original link
        while(ll){
            Node* nextll = ll->next;
            Node* tmp = new Node(ll->val);
            ll->next = tmp;
            tmp->next = nextll;
            ll = nextll;
        }
        // Handle random point First !!!!(next info exists)
        ll = head;
        
        while(ll){
            Node* cphead = ll->next;
            cphead->random = ll->random ? ll->random->next : nullptr;
            ll = cphead->next;
        }
		
        newhead = head->next;
        ll = head;
		// Handle next point and restore the original one
        while(ll){
            Node* cphead = ll->next;
            // 断开连接
            ll->next = cphead->next;

            cphead->next = cphead->next ? cphead->next->next : nullptr;
            ll = ll->next;
        }


        return newhead;
    }
};

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DBRichEdit关联ClientDataSet不能保存的Bug

ClientDataSet的最大好处&#xff0c;就是建立能内存表&#xff0c;特别DataSnap三层运用中&#xff0c;主要使用ClientDataSet与运程的服务器中的数据表&#xff0c;建立读取存贮关系。 在软件的使用中&#xff0c;总有客户反映&#xff0c;一些数据不能保存。 发现都是使用DB…

LeetCode讲解篇之347. 前 K 个高频元素

347. 前 K 个高频元素 文章目录 347. 前 K 个高频元素题目描述题解思路题解代码 题目描述 题解思路 根据数组频率倒序排序, 然后返回前k的个数据 题解代码 func topKFrequent(nums []int, k int) []int {m : make(map[int]int, 0)for i : len(nums) - 1; i > 0; i-- {m[n…

前端框架之争:Vue.js vs. React.js vs. Angular

文章目录 Vue.js - 渐进式框架的魅力简单易用组件化开发生态系统和工具适用场景 React.js - 高性能的虚拟DOM虚拟DOM单向数据流社区和生态系统适用场景 Angular - 一站式框架完整的框架双向数据绑定类型安全适用场景 如何选择&#xff1f;项目规模生态系统技能和经验性能需求 结…

win11 允许使用脚本Set-ExecutionPolicy

目录 Set-ExecutionPolicy RemoteSigned notepad.exe $PROFILE Set-ExecutionPolicy RemoteSigned Set-ExecutionPolicy RemoteSigned 如果报错&#xff0c;执行&#xff1a; Set-ExecutionPolicy -Scope CurrentUser 然后就会提示我们输入&#xff0c;我们把刚刚的 Remot…

【RocketMQ】(五)消息的消费

消费者从Broker拉取到消息之后&#xff0c;会将消息提交到线程池中进行消费&#xff0c;RocketMQ消息消费是批量进行的&#xff0c;如果一批消息的个数小于预先设置的批量消费大小&#xff0c;直接构建消费请求ConsumeRequest将消费请求提交到线程池处理&#xff0c;否则需要分…

Codeforces Round #898 (Div. 4)

首先庆祝自己上了绿名&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384;&#x1f384; 1873A - Short Sort 1873B - Good Kid c…

Verilog 不同编码风格对综合电路的影响

文章目录 示例 #1示例 #2示例 #3 Verilog是一种硬件描述语言&#xff08;HDL&#xff09;&#xff0c;用于设计数字电路和系统。统一、良好的代码编写风格&#xff0c;可以提高代码的可维护性和可读性。 同样的功能&#xff0c;不同的Verilog 编码风格也会对综合过程产生重大影…

前端uniapp如何转base64使用uniapp插件市场

插件市场 网址 使用 可以下载&#xff0c;也可以引用&#xff0c;我是下载下来的引用 代码 正常使用 pathToBase64(img).then(path > {img pathresolve(path)}).catch(error > {console.error(error)reject(error)})使用出现[object Promise]错误 解决方法 let img …

《动手学深度学习 Pytorch版》 7.4 含并行连接的网络(GoogLeNet)

import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2l7.4.1 Inception块 GoogLNet 中的基本卷积块叫做 Inception 块&#xff08;大概率得名于盗梦空间&#xff09;&#xff0c;由 4 条并行路径组成。 前 3 条路径使用窗口…

Spring面试题17:Spring中什么是bean装配?有哪几种自动装配方式?自动装配有哪些局限性?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring中什么是bean装配? 在Spring中,Bean装配是指将一个或多个Bean实例化、配置和组合在一起的过程。它是Spring容器的核心功能之一,通过Bean装…

宏基因组做在线组间差异Anosim分析与结果解读

写在前面 需求是返回的结果每组样本数量比较多&#xff0c;但组间差异不明显&#xff0c;挑出来重分析。详情请参考 [组间差异分析&#xff1a;Anosim]([组间差异分析&#xff1a;Anosim - 知乎 (zhihu.com))&#xff0c; 当然亲测更简便的方法可以借助云平台工具&#xff1a;…

ROS2 的行为树 — 第 1 部分:解锁高级机器人决策和控制

一、说明 在复杂而迷人的机器人世界中&#xff0c;行为树&#xff08;BT&#xff09;已成为决策过程中不可或缺的一部分。它们提供了一种结构化、模块化和高效的方法来对机器人的行为进行编程。BT起源于视频游戏行业&#xff0c;用于控制非玩家角色&#xff0c;他们在机器人领域…

面试官:为什么说HTTPS比HTTP安全? HTTPS是如何保证安全的?

公众号 小册 这是我整理的学习资料&#xff0c;非常系统和完善&#xff0c;欢迎一起学习 现代JavaScript高级小册 深入浅出Dart 现代TypeScript高级小册 linwu的算法笔记&#x1f4d2; 一、安全特性 在前文中&#xff0c;我们已经了解到HTTP在通信过程中存在以下问题&…

【pytest】 allure 生成报告

1. 下载地址 官方文档; Allure Framework 参考文档&#xff1a; 最全的PytestAllure使用教程&#xff0c;建议收藏 - 知乎 https://github.com/allure-framework 1.2安装Python依赖 windows&#xff1a;pip install allure-pytest 2. 脚本 用例 import pytest class …

【Hash表】字母异位词分组-力扣 49 题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

Linux 文件 目录管理 链接

Linux 文件 基本属性 Linux 系统是一种典型的多用户系统&#xff0c;为了保护系统的安全性&#xff0c;不同的用户拥有不同的地位和权限。Linux 系统对不同的用户访问同一文件&#xff08;包括目录文件&#xff09;的权限做了不同的规定。 可以使用命令&#xff1a;ll 或 ls –…

vue点击容器外隐藏元素(点击非本身以外的部分隐藏元素)

如图点击蓝色边框以外任意地方隐藏蓝色边框容器&#xff08;不使用输入框的失焦事件&#xff09; 实现思路&#xff1a; 获取到dom节点然后通过其contains方法来判断点击的地方是否为其子元素或其本身 原生js获取dom跟vue的$el都可以实现 也可以通过vue的this.$refs.showBox…

MinGW相关错误

1、go编译c报错 cc1.exe: sorry, unimplemented: 64-bit mode not compiled in 参考&#xff1a;BeifangCc go编译c报错 cc1.exe: sorry, unimplemented: 64-bit mode not compiled in 说明当前gcc是32位&#xff0c;无法在当前64位机器上正常工作&#xff0c;需要更新gcc 下载…

Unity打包出来的APK文件有问题总结

一、Unity打包出来的APK文件安装失败&#xff0c;提示安装失败&#xff08;-108&#xff09;&#xff0c;或者是提示“包含病毒&#xff1a;a.gray.Bulimia.b” 有可能是遇到如上图所示的问题&#xff0c;提示安装失败&#xff08;-108&#xff09;。 有可能是遇到如上图所示的…

java入坑之Jsoup(待补充)

一、快速入门 1.1配置 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.16.1</version> </dependency>1.2解析xml Jsoup&#xff1a;jsoup 是一款Java 的HTML解析器&#xff0c;可直接解…