如图1所示,有一条单链表,其节点除了有next指针外,还有一个random指针。random指针可指向单链表中的任意节点,包括它自身。random指针一旦指定,便不再更改。请设计算法,复制此单链表,并给出时间复杂度。

图1 带有random指针的单链表

解法1. 时间复杂度为O(n*n)

先按next指针,将链表复制一份。使用p1指向原链表的头节点,p2指向p1指向的节点的random节点,p3指向p1的next节点,cnt记录p3移动的步数,p4指向新链表的头节点。对比p3和p2的指向:如果p2和p3地址不一致,则p3移向本节点的next节点,并记录移动的频数加1。如此反复,直到p3指向的地址与p2指向的地址一致。使用p5指向p4的next节点,再向后移动cnt次,得到p4指向的节点的random指针应该指向的位置。将p1和p4同时移向各自的next。如此反复。

解法2. 时间复杂度为O(2n)

想要降低时间复杂度,就需要增加空间复杂度,拿空间换时间。解法1的时间复杂度高的原因为查找新链表中random指针的指向,哈希表可解决查找慢的问题。

可建立一个hash表,使用原链表的节点的地址的hash值作下标,使用新链表对应的地址作value。这样遍历原链表一遍后,节点的random指向为NULL的新链表可建立起来,并且建立了一张hash表。再遍历一遍,p1指向原链表中某节点,p2指向新链表中对应的某节点。将p1的random指针指向的地址做hash后,可得到hash表中新链表对应的地址值。再将p2的random指针指向该地址即可。如此反复。

解法3. 时间复杂度为O(2n),空间复杂度为O(1)

解法2所花费的空间有些大了,解决法通破坏原链表的方法,代替了hash表,解决了查找random指针指向的问题。虽然原链表被破坏了,但可被恢复到原样。

首先遍历原链表,同时建立新链表。将新链表的random指针指向原链表对应节点的next节点,将原链表的next指针指向新链表的对应节点。

再遍历一次原链表和新链表,p1指向原链表的某节点,p2指向新链表的对应节点。从p1可知random指向的节点,从此节点的next指针可知新链表的对应节点,使用p3指针指向该节点。将p1的next指向p2的random指针指向的节点,再将p2的random指针指向p3。p1和p2均指向自己的next节点。如此反复。

解法3的示意图如下:

RandomListNode *copyRandomList(RandomListNode *head) {  // write your code here  RandomListNode *p = head;  RandomListNode *dest, *t = NULL;  while (p != NULL) {  t = new RandomListNode(p->label);  t->next = p->next;  t->random = p->random;  p->next = t;  p = t->next; //取得源链表中的下一个结点  }  p = head;  while (p != NULL) {  t = p->next;  if (t->random != NULL) {  // 此处需要判断源节点的random是否为空,如果不为空才需要更新  t->random = t->random->next;  }  p = t->next;  }  p = head;  dest = p->next;  while (p != NULL) {  t = p->next;  p->next = t->next; //新旧链表分离的旧(源)链表  p = t->next;  if (p != NULL) {  t->next = p->next;  //新旧链表分离的新链表  }  }  return dest;  }  

复制带有random指针的单链表相关推荐

  1. 算法练习day10——190328(根据指定值划分单链表、复制含有rand指针节点的链表、两个单链表相交)

    1.将单向链表按某值划分成左边小. 中间相等. 右边大的形式 [题目] 给定一个单向链表的头节点head, 节点的值类型是整型, 再给定一个整数pivot. 实现一个调整链表的函数, 将链表调整为左部 ...

  2. 左神算法:复制含有随机指针节点的链表 / 复杂链表的复制(Java版本)

    本题来自左神<程序员代码面试指南>"复制含有随机指针节点的链表"题目. 题目 一种特殊的链表节点类描述如下: public static class Node {pub ...

  3. (关于单链表的真题)已知一个带有表头结点的单链表...请设计一个尽可能高效的算法,查找链表中倒数第k个位置的结点。

    真题描述 已知一个带有表头结点的单链表,结点结构为 data next 假设该链表只给出了头指针head.在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点. 若查找成 ...

  4. 数据结构与算法之复制含有随机指针节点的链表和两个链表相交的一系列问题

    数据结构与算法复制含有随机指针节点的链表和两个链表相交的一系列问题 目录 复制含有随机指针节点的链表 两个链表相交的一系列问题 1. 复制含有随机指针节点的链表 题目概述 思路:创建一个HashMap ...

  5. 已知一个带有表头结点的单链表,结点结构为 data link 假设该链表只给出了头指针list。在不改变链表的前提下,请设计一个尽可能高效的 算法,查找链表中倒数第k个位置

    分析: 这是一个单链表算法题,题中说要在不改变链表本身的前提下,设计一个尽可能高效的算法,说明时间复杂度.空间复杂度都要尽可能地高效,常数也要尽可能小. 思路: 设置两个指针p和q,指p针在指针q后k ...

  6. 链表问题9——复制含有随机指针节点的链表(进阶)

    题目 具体题目信息可以参考上一篇文章. 进阶:不使用额外的数据结构,只用有限几个变量,且在时间复杂度为O(N)内完成原问题要实现的函数. 思路 进阶解法不使用哈希表来保存对应关系,而只采用有限的几个变 ...

  7. 链表问题9——复制含有随机指针节点的链表(初阶)

    题目 public class Node{public int value;public Node next;public Node rand;public Node(int data){this.v ...

  8. 单链表-删除并释放以L为表头指针的单链表的所有结点(双指针法)

    单链表的存储结构: typedef struct LinkList{int data;LinkList * next;} 分析: 要删除所有结点,怎么删除? 往往都要定义前后指针 pre ,p 毕竟一 ...

  9. 复制含有随机指针节点的链表~哈希表的使用~(⌒▽⌒)

    题目意思就是说给你给head 的Node节点(这是一个比较特殊的链表),来拷贝出它地结构出来. 方法一:借助HashMap的特性,定义一个HashMap<Node,Node> map对象, ...

最新文章

  1. 华师大数据科学考研_2020年华东师范大学行政管理专业考研报录比、参考书目、考研经验分享...
  2. Editplus下载、安装并最佳配色方案(强烈推荐)
  3. Bootstrap—基础样式定义
  4. 本周 Github 精选:多款超赞 AI 开源项目,等你来 Star!
  5. matlab中的@函数
  6. Asp.Net MVC项目通过Git同步到新开发设备上后无法作为网站启动
  7. 维修点滴:键盘进杂物
  8. java 删除txt,如何从.txt文件中删除2个值
  9. PLSQL创建用户及权限分配
  10. 死锁发生的条件和预防
  11. 协议圣经 五 rtsp client
  12. 简述Java Object类中的方法有哪些
  13. Objective-c nil, Nil, NULL和NSNull的区别
  14. 有必要考国二mysql_国二证有用吗
  15. 大数据告诉你,中国哪里出美女
  16. 我的世界服务器客户端制作,《我的世界》宇瑄服务器客户端mod
  17. delphi math 单元函数
  18. RN新架构 JSI 介绍
  19. 滑动窗口算法思想,找出字符串中的所有字母异位词
  20. [Ubuntu 16.04] [Memos] install ssh

热门文章

  1. 帮我写一个批量取消抖音喜欢的Python代码
  2. CFTC主席称分布式账本技术可以帮助市场监管
  3. SPPNet网络模型
  4. win10+联想小新pro13无法访问网络问题
  5. Dubbo 面试题大全
  6. 日志logger的使用
  7. Kooboo CMS 无聊随笔 (1)
  8. juicer html拼接,juicer.js的使用
  9. Jason格式化Google插件FeHelper(Get请求)
  10. windows下虚拟环境的安装与使用