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

链表学习之复制含随机指针的链表

链表解题技巧

  • 额外的数据结构(哈希表);
  • 快慢指针;
  • 虚拟头节点;

复制含随机指针的链表

该链表节点的结构如下:

class ListRandomNode {
public:ListRandomNode() : val(0), next(nullptr), random(nullptr) {}ListRandomNode(int v, ListRandomNode *n, ListRandomNode *r) : val(v), next(n), random(r) {}
public:int val;ListRandomNode *next;ListRandomNode *random;
};

要求:时间复杂度O(N),空间复杂度O(1);

方法1:哈希表

时间复杂度O(N),空间复杂度O(N);

具体思路:

  • 遍历链表,复制每个节点并存入map,key为原节点,val为新节点;
  • 再次遍历链表,每个新节点都可以通过源节点和map找到,据此连接next和random;
    • 新节点的next就是,map[源节点]的next;
    • 新节点的random就是,map[源节点]的random;
ListRandomNode* LinkedList::copyListWithRandomByMap(ListRandomNode *head) {if (head == nullptr ) return head;std::unordered_map<ListRandomNode*, ListRandomNode*> ref;// create new nodeListRandomNode *cur = head;while (cur != nullptr) {ListRandomNode *tmp = new ListRandomNode(cur->val, nullptr, nullptr);ref[cur] = tmp;cur = cur->next;}// joint new nodecur = head;while (cur != nullptr) {ref[cur]->next = ref[cur->next];ref[cur]->random = ref[cur->random];cur = cur->next;}return ref[head];
}

方法2:next

时间复杂度O(N),空间复杂度O(1);

将每一个新节点放在原来节点的后面,并连接上下一个节点的方式,这样通过next就能够定位到新节点,通过next的next就能找到原来的下一个节点。

  • 遍历一遍链表,遍历的过程中,为每一个节点创建一个新节点,新节点连接在原来两个节点之间;
  • 再次遍历链表,为random赋值:新节点的random就是,源节点random的next;
  • 再将源节点和新节点分离出来,返回新节点头即可。
ListRandomNode* LinkedList::copyListWithRandom(ListRandomNode *head) {if (head == nullptr) return head;// create new nodeListRandomNode *cur = head;while (cur != nullptr) {ListRandomNode *cur_ = new ListRandomNode(cur->val, nullptr, nullptr);ListRandomNode *tmp = cur->next;cur->next = cur_;cur_->next = tmp;cur = tmp;}// assign random pointerscur = head;while (cur != nullptr) {cur->next->random = cur->random ? cur->random->next : nullptr;cur = cur->next->next;}// splitcur = head;ListRandomNode *new_head = head->next;ListRandomNode *cur_ = head->next;while (cur_->next != nullptr) {cur->next = cur_->next;cur = cur->next;cur_->next = cur->next;cur_ = cur_->next;}cur->next = nullptr;cur_->next = nullptr;return new_head;
}

辅助函数

根据数组生成带随机值的链表:

ListRandomNode* LinkedList::generateListWithRandom(int *arr, int len) {if (arr == nullptr || len < 1) {return nullptr;}std::vector<ListRandomNode*> vec;ListRandomNode *head = new ListRandomNode(arr[0], nullptr, nullptr);ListRandomNode *cur = head;for (int i = 1; i < len; i++) {vec.push_back(cur);cur->next = new ListRandomNode(arr[i], nullptr, nullptr);cur = cur->next;}vec.push_back(cur);for (int i = 0; i < len; i++) {vec[i]->random = vec[rand() % len];}return head;
}

打印随机链表:

void LinkedList::printListWithRandom(ListRandomNode *head) {while (head) {std::cout << head->val << "[" << head->random->val << "]" << (head->next ? "->" : " ") ;head = head->next;}std::cout << std::endl;
}
http://www.lryc.cn/news/11800.html

相关文章:

  • 【人脸检测】Yolov5Face:优秀的one-stage人脸检测算法
  • 【Unity3d】Unity与Android之间通信
  • Allegro如何更改DRC尺寸大小操作指导
  • Mongodb WT_PANIC: WiredTiger library panic
  • 【HTML】HTML 表格总结 ★★★ ( 表格标签 | 行标签 | 单元格标签 | 表格标签属性 | 表头单元格标签 | 表格标题标签 | 合并单元格 )
  • linux013之文件和目录的权限管理
  • 设计模式之状态模式
  • XQuery 选择 和 过滤
  • 室友打了一把王者的时间,我理清楚了grep,find,管道|,xargs的区别与联系,用的时候不知道为什么要这样用
  • python 刷题时常见的函数
  • Python之列表推导式和列表排序
  • 力扣(LeetCode)240. 搜索二维矩阵 II(C++)
  • golang defer
  • 【Java】线程的死锁和释放锁
  • 如何使用断点续传上传大文件
  • 【图神经网络】图拉普拉斯滤波器如何实现全通、低通、高通滤波
  • python操作mysql数据库详解
  • netty群聊系统
  • Android 初代 K-V 存储框架 SharedPreferences,旧时代的余晖?
  • 在windows中使用tomcat搭建Jenkins
  • Linux系统
  • Mel Frequency Cepstral Coefficients (MFCCs)
  • 第七讲---贪心(上课)
  • 计算机如何思考与图灵完备
  • 惠普LaserJet M1005 MFP报错b2
  • 网络协议(TCP/IP)
  • 2023河南省第二届职业技能大赛郑州市选拔赛“网络安全” 项目比赛样题任务书
  • 6、流程控制
  • Linux中最基本常见命令总结
  • Python学习-----模块2.0(常用模块之时间模块-->time)