复制带有random指针的单链表
如图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指针的单链表的更多相关文章
- 40深入理解C指针之---指针与单链表
一.指针与单链表 1.定义:通过使用指针将节点(结点)链接起来成为链表 2.节点(结点): 1).数据域:主要用来存储数据,可以基本数据类型,也可以是构造数据类型: 2).指针域:主要用来当前节点(结 ...
- [leetcode]138. Copy List with Random Pointer复制带有随机指针的链表
public RandomListNode copyRandomList(RandomListNode head) { /* 深复制,就是不能只是复制原链表变量,而是做一个和原来链表一模一样的新链表, ...
- LeetCode——Copy List with Random Pointer(带random引用的单链表深拷贝)
问题: A linked list is given such that each node contains an additional random pointer which could poi ...
- 复制一个带random指针的链表
一个单链表,其中除了next指针外,还有一个random指针,指向链表中的任意某个元素.如何复制这样一个链表呢? 通过next来复制一条链是很容易的,问题的难点在于如何恰当地设置新链表中的random ...
- 【链表问题】打卡9:将单链表的每K个节点之间逆序
前言 以专题的形式更新刷题贴,欢迎跟我一起学习刷题,相信我,你的坚持,绝对会有意想不到的收获.每道题会提供简单的解答,如果你有更优雅的做法,欢迎提供指点,谢谢. 注:如果代码排版出现了问题麻烦通知我下 ...
- 数据结构 - 动态单链表的实行(C语言)
动态单链表的实现 1 单链表存储结构代码描述 若链表没有头结点,则头指针是指向第一个结点的指针. 若链表有头结点,则头指针是指向头结点的指针. 空链表的示意图: 带有头结点的单链表: 不带头结点的单链 ...
- 《数据结构》2.3单链表(single linked list)
//单链表节点的定义 typedef struct node { datatype data; struct node *next; }LNode,*LinkList; //LNode是节点类型,Li ...
- 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现
概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...
- 删除单链表倒数第n个节点
基本问题 如何删除单链表中的倒数第n个节点? 常规解法 先遍历一遍单链表,计算出单链表的长度,然后,从单链表头部删除指定的节点. 代码实现 /** * * Description: 删除单链表倒数第n ...
随机推荐
- 记一次SSH登陆失败问题的定位
创建用户之后,使用ssh协议登陆提示失败. useradd -d /home/hdp -m hdp -g dba -s /bin/bash 通过命令 ssh -v hdp@127.0.0.1 登陆,查 ...
- BZOJ2150: 部落战争
题解: 把每个点拆成入点和出点,因为必须经过一次且只能经过一次.所以在两个点之间连一条上界=下界=1的边. 然后再s到每个入点连边,每个出点向t连边,点与点之间... 求最小流就可以过了... (感觉 ...
- set xact_abort 用法
默认行为 默认为SET XACT_ABORT OFF,没有事务行为. SET XACT_ABORT ON SET XACT_ABORT ON分为两种: 1.总体作为一个事务,整体提交或整体回滚,格式为 ...
- Idea无法DEBUG的问题
最近对web工程进行debug,突然发现无法进入断点了,原来以为是maven的问题,后来发现是tomcat环境变量导致的. 使用tomcat时经常碰到内存不足的情况,我们会对catalina.bat类 ...
- jquery自动焦点图
效果预览:http://runjs.cn/detail/vydinibc 带左右箭头的自动焦点图:http://runjs.cn/detail/wr1d1keh html: <div clas ...
- Android学习系列(1)--为App签名(为apk签名)
写博客是一种快乐,前提是你有所写,与人分享,是另一种快乐,前提是你有舞台展示,博客园就是这样的舞台.这篇文章是android开发人员的必备知识,是我特别为大家整理和总结的,不求完美,但是有用. 1.签 ...
- 编写高效的C程序与C代码优化 via jobbole
http://blog.jobbole.com/82582/ 原文出处: codeproject 译文出处:CodingWu的博客 欢迎分享原创到伯乐头条
- ARM Linux 如何--注册和触发--软中断
1. 注册软中断当然是通过open_softirq 例子如下: void __init init_timers(void) { int err = timer_cpu_notify(&time ...
- HDU5046 Airport dancing links 重复覆盖+二分
这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮 ...
- 黑盒测试用例设计方法&理论结合实际 -> 错误推断法
一 概念 基于经验和直觉推测程序中所有可能存在的各种错误, 从而有针对性的设计测试用例的方法. 二 错误推断法的应用 基本思想:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试 ...