如图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的示意图如下:

最新文章

  1. COGS2531. [HZOI 2016]函数的美 打表+欧拉函数
  2. Redis集群最佳实践
  3. 【数据结构】平衡二叉树—AVL树
  4. scrollview技巧
  5. EL表达式详解
  6. menu({postion:{my:"left top"},at:"right bottom"})里的my与at会冲突吗
  7. Flume Spooldir 源的一些问题
  8. 【OpenGL】入门
  9. 第七篇: python高级之多线程
  10. 最全的C#图片处理帮助类ImageHelper
  11. WF学习
  12. FCKeditor
  13. JQ----树杈型导航
  14. Win95+IE3 – Win10+IE11全版本执行漏洞(含POC)
  15. 线程UI同步
  16. nginx虚拟域名的配置以及测试验证
  17. 巡风源码阅读与分析---AddPlugin()方法
  18. shell实战之Linux主机系统监控
  19. HTML、CSS知识点,面试开发都会需要--No.6 设置背景
  20. webscoket通信初步(一)

热门文章

  1. HTML5学习(十一)---服务器发送事件
  2. 武汉北大青鸟解读2016年10大IT热门岗位
  3. Innodb引擎 long semaphore waits
  4. 彩色网页变黑白色CSS代码变黑白色调!
  5. EF的表连接方法Include() - nlh774
  6. C#用DES加密JAVA用DES解密,JAVA用DES加密C#用DES解密的实现
  7. c#保存datagridview中的数据时报错 “动态SQL生成失败。找不到关键信息”
  8. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.5.3
  9. Jmeter初步使用--Jmeter安装与使用
  10. Struts2 Spring Hibernate Ajax Java总结(实时更新)