给大家推荐一道leetcode上的面试题,这道题的详细解说在《剑指offer》的P149页有思路解说。假设你手头有这本书。建议翻阅。

题目链接 here

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

RandomList中。每一个节点不光有一个next指针。并且每一个链表节点都有一个random指针。随机指向链表中的一个节点,让你复制这个链表,节点的C++定义例如以下。

/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/

看到这个题目,预计非常多人的第一反应是,先把这个单链表复制出来,然后挨个找random指向的节点。细致想想这样效率非常低。复制链表非常快。但确定每一个节点的random指针就不easy了,用这样的方法的话。每找一个random指针,都必须遍历一次链表。时间复杂度O(n^2)。

可能也有人可能会想到时间换空间的方法,用hash把时间复杂度降到O(n)。

当然,还有更省时省空间的方法。

大概思路就是,在原链表的基础上,把每一个节点复制一份加的原来节点的后面,然后设置好新节点random指针,在把全部的新节点从原链表中分离出来。构成一个新链表,这个链表就是我们要的原链表的拷贝。

以下有三个函数,第一个明显就是复制新节点并把其增加到被复制节点的后面。第二个。由于新节点的random指针还是指向旧节点的。要把它指向新节点。非常easy,由于每一个节点的新节点都是在原来的节点之后的。

第三个函数。把新节点从原链表中抽离,构成一个新链表。

这样的方法的优点就是。时间复杂度仅仅有O(n),并且我们不须要额外的空间。

class Solution {
public:
void CloneNode(RandomListNode *head) {
RandomListNode * p = head;
while (NULL != p) {
RandomListNode * CloneNode = new RandomListNode(p->label);
CloneNode->next = p->next;
CloneNode->random = p->random;
p->next = CloneNode;
p = CloneNode->next;
}
} void ConnectRandomNode(RandomListNode * head) {
RandomListNode * p = head;
while (NULL != p) {
RandomListNode *pclone = p->next;
if (NULL != pclone->random) {
pclone->random = pclone->random->next;
}
p = pclone->next;
}
}
RandomListNode *copyRandomList(RandomListNode *head) {
if (NULL == head)
return head;
CloneNode(head);
ConnectRandomNode(head);
RandomListNode *pnode = head;
RandomListNode *pclonehead = pnode->next;
RandomListNode *pclonenode = pnode->next;
while (NULL != pnode) {
pnode->next = pclonenode->next;
pnode = pnode->next;
if (NULL != pnode){
pclonenode->next = pnode->next;
pclonenode = pclonenode->next;
}
}
return pclonehead;
} };

最新文章

  1. U-BLOX GPS 模块及GPRMC指令解析
  2. ORACLE 错误:oralce record is locked by another user
  3. 【leetcode❤python】 1. Two Sum
  4. Ubuntu上部署一个简单的Java项目
  5. HangOver
  6. SAP保存操作记录CDHDR和CDPOS表
  7. ios7 导航栏 手势 右划 自动返回 相关
  8. OpenGL超级宝典第5版&&GLSL法线变换
  9. mysql 数据库连接池
  10. inno setup 跳过(Welcome)欢迎界面
  11. Spark学习资料
  12. Delphi使用大图标编译程序
  13. 学习MVC之租房网站(二)-框架搭建及准备工作
  14. windows系统操作
  15. POJ 1681 Painter's Problem [高斯消元XOR]
  16. QQ数据库管理
  17. 我也来----xia bi bi 一下----微信小程序
  18. Python基础(六)_全局变量声明、可变参数、关键字参数
  19. redis主从复制详述
  20. Structured Streaming教程(1) —— 基本概念与使用

热门文章

  1. Lower dc/dc-converter ripple by using optimum capacitor hookup
  2. @JsonInclude(Include.NON_NULL)
  3. linux shell 正则表达式(BREs,EREs,PREs)差异比较(转,当作资料查)
  4. 第一篇 对Javascript中原型的深入理解
  5. 数学图形(2.23)Cylindric sine wave柱面正弦曲线
  6. 数学图形(2.5)Loxodrome曲线
  7. Symfony安装及使用
  8. Hydra 无法爆破SSH 解决办法
  9. Orchard运用 - 导入旧随笔导致归档的问题
  10. J2EE 中 用 El表达式 和 Jsp 方式 取得 URL 中的参数方法