当前位置: 首页 > backend >正文

138. Copy List with Random Pointer

目录

题目描述

方法一、使用哈希表

方法二、不使用哈希表


题目描述

 

问题的关键是,random指针指向的是原链表的结点,这个原链表的结点对应哪一个新链表的结点呢?有两种办法。一是用哈希表。另一种是复制原链表的每一个结点,并将新结点接在原结点的后面组成一个长度加倍的链表,这样原结点的直接后继就是该原结点对应的新结点。

方法一、使用哈希表

unordered_map<Node*,Node*> new_table;//键是原链表中的旧结点,值是新链表中的新结点

unordered_map<Node*,Node*> random_table;//键是原链表中的旧结点,值是该旧结点的random指针指向的结点

/*
// 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 == nullptr)return nullptr;unordered_map<Node*,Node*> new_table;//键是原链表中的旧结点,值是新链表中的新结点unordered_map<Node*,Node*> random_table;//键是原链表中的旧结点,值是该旧结点的random指针指向的结点Node* newHead = nullptr;Node* newTail = nullptr;Node* cur = head;//第一步,建立新链表while(cur){Node* node = new Node(cur->val);new_table.insert({cur,node});random_table.insert({cur,cur->random});if(newHead == nullptr){newHead = node;newTail = node;}else{newTail->next = node;newTail = node;}cur = cur->next;}//第二步,设置新链表结点的random指针for(const auto& [old_node,new_node] : new_table){if(random_table[old_node]){new_node->random = new_table[random_table[old_node]];}}return newHead;}
};

实际上前面做法中的random_table是可以不需要的。

/*
// 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 == nullptr)return nullptr;unordered_map<Node*,Node*> new_table;//键是原链表中的旧结点,值是新链表中的新结点Node* newHead = nullptr;Node* newTail = nullptr;Node* cur = head;//第一步,建立新链表while(cur){Node* node = new Node(cur->val);new_table.insert({cur,node});if(newHead == nullptr){newHead = node;newTail = node;}else{newTail->next = node;newTail = node;}cur = cur->next;}cur = head;Node* new_cur = newHead;//第二步,设置新链表结点的random指针while(cur){if(cur->random){new_cur->random = new_table[cur->random];}cur = cur->next;new_cur = new_cur->next;}return newHead;}
};

方法二、不使用哈希表

第一步,复制每一个旧结点,并将新结点接在旧结点的后面组成新旧结点交替出现的长度翻倍的大链表。

第二步,设置新结点的random指针。

第三步,从大链表中提取出新结点组成新链表,并将原链表复原。

需要着重强调的是,第二步和第三步必须分开来做。

/*
// 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 == nullptr)return nullptr;Node* cur = head;//复制每一个旧结点,并将新结点接在旧结点的后面while(cur){Node* node = new Node(cur->val);Node* temp = cur->next;node->next = cur->next;cur->next = node;cur = temp;}cur = head;//设置新结点的random指针while(cur){if(cur->random)cur->next->random = cur->random->next;cur = cur->next->next;//原链表向前走一位}Node* new_head = nullptr;Node* new_tail = nullptr;cur = head;//提取出新结点组成新链表,并将原链表复原while(cur){if(new_head == nullptr){new_head = cur->next;new_tail = cur->next;}else{new_tail->next = cur->next;new_tail = cur->next;}cur->next = cur->next->next;//复原原链表cur = cur->next;//原链表向前走一步}return new_head;}
};
http://www.xdnf.cn/news/7818.html

相关文章:

  • Docker 镜像打包到本地
  • Android开发——不同布局的定位属性 与 通用属性
  • 大数据量查询优化:解锁SQL性能提升的关键
  • Node.js多版本安装工具NVM详细使用教程
  • VsCode开发环境之Node.js离线部署
  • JS 应用安全案例泄漏云配置接口调试代码逻辑框架漏洞自检
  • 华为鸿蒙电脑发布,折叠屏怎么选?
  • 实现动态增QuartzJob,通过自定义注解调用相应方法
  • OpenCV CUDA模块特征检测与描述------一种基于快速特征点检测和旋转不变的二进制描述符类cv::cuda::ORB
  • WPF核心类继承树结构
  • 学习路之uniapp--unipush2.0推送功能--服务端推送消息
  • Java安全-Servlet内存马
  • 基于多传感器融合的智能驾驶环境感知系统
  • 【java第19集】java面向对象编程详解
  • MyBatis:简化数据库操作的持久层框架
  • 高噪声下扩展边缘检测算子对检测边缘的影响
  • windows powershell 判断 进程号是否存在
  • 无人机桥梁巡检
  • linux文件重命名命令
  • MIL-C-5015航空插头2芯震动加速度传感器连接器
  • 五、【API 开发篇(下)】:使用 Django REST Framework构建测试用例模型的 CRUD API
  • 云原生安全之PaaS:从基础到实践的技术指南
  • 谈谈 Kotlin 中的构造方法,有哪些注意事项?
  • 【Django系统】Python+Django携程酒店评论情感分析系统
  • 【Java微服务组件】异步通信P2—Kafka与消息
  • [杂学笔记]浏览器多进程与多线程架构、wstring类型、哈希表、红黑树与哈希表的对比、C++标准库Random类
  • 影响镍钯金PCB表面处理价格的因素有哪些?
  • Spring事务简单操作
  • 【低代码】如何使用明道云调用 Flask 视图函数并传参(POST 方法实践)
  • vue-cli 构建打包优化(JeecgBoot-Vue2 配置优化篇)