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

复制带有random指针的单链表的更多相关文章

  1. 40深入理解C指针之---指针与单链表

    一.指针与单链表 1.定义:通过使用指针将节点(结点)链接起来成为链表 2.节点(结点): 1).数据域:主要用来存储数据,可以基本数据类型,也可以是构造数据类型: 2).指针域:主要用来当前节点(结 ...

  2. [leetcode]138. Copy List with Random Pointer复制带有随机指针的链表

    public RandomListNode copyRandomList(RandomListNode head) { /* 深复制,就是不能只是复制原链表变量,而是做一个和原来链表一模一样的新链表, ...

  3. LeetCode——Copy List with Random Pointer(带random引用的单链表深拷贝)

    问题: A linked list is given such that each node contains an additional random pointer which could poi ...

  4. 复制一个带random指针的链表

    一个单链表,其中除了next指针外,还有一个random指针,指向链表中的任意某个元素.如何复制这样一个链表呢? 通过next来复制一条链是很容易的,问题的难点在于如何恰当地设置新链表中的random ...

  5. 【链表问题】打卡9:将单链表的每K个节点之间逆序

    前言 以专题的形式更新刷题贴,欢迎跟我一起学习刷题,相信我,你的坚持,绝对会有意想不到的收获.每道题会提供简单的解答,如果你有更优雅的做法,欢迎提供指点,谢谢. 注:如果代码排版出现了问题麻烦通知我下 ...

  6. 数据结构 - 动态单链表的实行(C语言)

    动态单链表的实现 1 单链表存储结构代码描述 若链表没有头结点,则头指针是指向第一个结点的指针. 若链表有头结点,则头指针是指向头结点的指针. 空链表的示意图: 带有头结点的单链表: 不带头结点的单链 ...

  7. 《数据结构》2.3单链表(single linked list)

    //单链表节点的定义 typedef struct node { datatype data; struct node *next; }LNode,*LinkList; //LNode是节点类型,Li ...

  8. 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

    概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...

  9. 删除单链表倒数第n个节点

    基本问题 如何删除单链表中的倒数第n个节点? 常规解法 先遍历一遍单链表,计算出单链表的长度,然后,从单链表头部删除指定的节点. 代码实现 /** * * Description: 删除单链表倒数第n ...

随机推荐

  1. linux切换用户

    当前使用root账户 [root@localhost chucklu]# cd[root@localhost ~]# pwd/root 切换到普通账户 [root@localhost ~]# su c ...

  2. Export BOM - BOMPXINQ.EXPLODER_USEREXIT API

    --======================================================================== -- Procedure    : explode ...

  3. UVa 11040 (水题) Add bricks in the wall

    题意: 45块石头如图排列,每块石头上的数等于下面支撑它的两数之和,求其余未表示的数. 分析: 首先来计算最下面一行的数,A71 = A81 + A82 = A91 + 2A92 + A93,变形得到 ...

  4. Gentoo安装

    Gentoo Linux安装详解--根据官方WiKi整理 时间:2014-06-26 06:37:54      阅读:549      评论:0      收藏:0      [点我收藏+] 标签: ...

  5. 【转】android新建项目时 出现appcompat_v7工程错误和红色感叹号

    原文网址:http://www.cnblogs.com/xiaozhang2014/p/4109856.html 最近初学android,版本是22.6.0的话,每次创建一个项目就会出现一个appco ...

  6. Event事件详解

    首先提到event,先要明白event的产生,也要先明白焦点,什么是焦点.焦点 : 使浏览器能够区分用户输入的对象,当一个元素有焦点的时候,那么他就可以接收用户的输入. 我们可以通过一些方式给元素设置 ...

  7. 理解dojo.require机制

    转自:http://blog.csdn.net/dojotoolkit/article/details/5935844 Dojo 提供了一个非常强大的javascript控件库. 在使用dojo之前, ...

  8. vs2010调用matlab2011下的.m文件

    很幸运在网上找到了采用引擎的方法,用vs2009调用matlab2008下的.m文件:但个人的环境是vs2010+matlab2011;想着二者差不多,故将s2010调用matlab2008拿来试试: ...

  9. Java序列化 如何把多个对象存储在一个文件中

    /** * 用于保存模板文件,内容包括: * 1,标志位,1 int * 2,版本   1 int * 3,数据头长度 1 int * 4,预留数据头空间  5120 byte * 5,后续数据长度  ...

  10. JRebel 5.3.2

    http://www.blogjava.net/xylz/archive/2013/09/15/404098.html   此为单文件版本,无需license文件 IDE(Eclipse.IDEA可能 ...