(剑指Offer)面试题26:复杂链表的复制
题目:
请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。
在复杂链表中,每个结点除了有一个pNext指针指向下一个结点之外,还有一个pSibling指向链表中的任意结点或者NULL。
结点的定义如下:
struct ComplexListNode{
int val;
ComplexListNode* pNext;
ComplexListNode* pSibling;
};
思路:
方法1:
复制原始链表上的每一个结点,并通过pNext连接起来;然后再设置每个结点的pSibling指针。
假设原始链表中某个结点N的pSibling指针指向结点S,那么就需要从头到尾遍历查找结点S,如果从原始链表的头指针开始,经过m步之后达到结点S,那么在复制链表中的结点N'的pSibling指针指向的结点也是距离复制链表s步的结点。通过这种办法就可以为复制链表上的每个结点设置pSibling指针。
时间复杂度:O(N^2)
方法2:
方法1是通过链表查找来得到pSibling指针所指向的结点,实际上我们可以通过空间换取时间,将原始链表和复制链表的结点通过哈希表对应起来,这样查找的时间就从O(N)变为O(1)。具体如下:
复制原始链表上的每个结点N创建N',然后把这些创建出来的结点用pNext连接起来。同时把<N,N'>的配对信息方法一个哈希表中;然后设置复制链表中的每个结点的pSibling指针,如果原始链表中结点N的pSibling指向结点S,那么在复制链表中,对应的N'应该指向S'。
时间复杂度:O(N)
方法3:
在不使用辅助空间的情况下实现O(N)的时间效率。
第一步:根据原始链表的每个结点N创建对应的N',然后将N‘通过pNext接到N的后面;
第二步:设置复制出来的结点的pSibling。假设原始链表上的N的pSibling指向结点S,那么其对应复制出来的N'是N->pNext指向的结点,同样S'也是结点S->pNext指向的结点。
第三步:把长链表拆分成两个链表,把奇数位置的结点用pNext连接起来的就是原始链表,把偶数位置的结点通过pNext连接起来的就是复制链表。
代码:
1、Hash方法:
struct ComplexListNode{
int val;
ComplexListNode* pNext;
ComplexListNode* pSibling;
ComplexListNode():val(0),pNext(NULL),pSibling(NULL){};
};
typedef std::map<ComplexListNode*,ComplexListNode*> MAP;
ComplexListNode* CloneNodes(ComplexListNode* pHead,MAP &hashNode){
ComplexListNode* pNode=new ComplexListNode();
ComplexListNode* p=pNode;
ComplexListNode* tmp;
while(pHead!=NULL){
tmp=new ComplexListNode();
tmp->val=pHead->val;
p->pNext=tmp;
hashNode[pHead]=tmp;
pHead=pHead->pNext;
p=p->pNext;
}
return pNode->pNext;
}
void SetSiblings(ComplexListNode* pHead,ComplexListNode* pCopy,MAP &hashNode){
while(pCopy!=NULL){
pCopy->pSibling=hashNode[pHead->pSibling];
pCopy=pCopy->pNext;
pHead=pHead->pNext;
}
}
ComplexListNode* ComplexListCopy(ComplexListNode* pHead){
ComplexListNode* pCopy;
MAP hashNode;
pCopy=CloneNodes(pHead,hashNode);
SetSiblings(pHead,pCopy,hashNode);
return pCopy;
}
2、复制连接方法:
#include <iostream>
using namespace std;
struct ComplexListNode{
int val;
ComplexListNode* pNext;
ComplexListNode* pSibling;
ComplexListNode(int x):val(x),pNext(NULL),pSibling(NULL){};
};
void CloneNodes(ComplexListNode* pHead){
ComplexListNode* pNode=pHead;
ComplexListNode* pCloned;
while(pNode!=NULL){
pCloned=new ComplexListNode(pNode->val);
pNode->pNext=pCloned;
pCloned->pNext=pNode->pNext;
pNode=pCloned->pNext;
}
}
void ConnectSiblingNodes(ComplexListNode* pHead){
ComplexListNode* pNode=pHead;
ComplexListNode* pCloned;
while(pNode!=NULL){
pCloned=pNode->pNext;
if(pNode->pSibling!=NULL){
pCloned->pSibling=pNode->pSibling->pNext;
}
pNode=pCloned->pNext;
}
}
ComplexListNode* ReconnectNodes(ComplexListNode* pHead){
ComplexListNode* pNode=pHead;
ComplexListNode* pClonedHead=NULL;
ComplexListNode* pClonedNode=NULL;
if(pNode!=NULL){
pClonedHead=pClonedNode=pNode->pNext;
pNode->pNext=pClonedNode->pNext;
pNode=pNode->pNext;
}
while(pNode!=NULL){
pClonedNode->pNext=pNode->pNext;
pClonedNode=pClonedNode->pNext;
pNode->pNext=pClonedNode->pNext;
pNode=pNode->pNext;
}
return pClonedHead;
}
ComplexListNode* Clone(ComplexListNode* pHead){
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}
在线测试OJ:
http://www.nowcoder.com/books/coding-interviews/f836b2c43afc4b35ad6adc41ec941dba?rp=1
AC代码:
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
typedef std::map<RandomListNode*,RandomListNode*> MAP;
RandomListNode* CloneNextNode(RandomListNode* pHead,MAP &hashNode){
RandomListNode* pCopy=new RandomListNode(0);
RandomListNode* p=pCopy;
RandomListNode* tmp;
while(pHead!=NULL){
tmp=new RandomListNode(pHead->label);
p->next=tmp;
hashNode[pHead]=tmp;
p=p->next;
pHead=pHead->next;
}
return pCopy->next;
} void setRandomNode(RandomListNode* pHead,RandomListNode* pCopy,MAP &hashNode){
while(pCopy!=NULL){
pCopy->random=hashNode[pHead->random];
pCopy=pCopy->next;
pHead=pHead->next;
}
} RandomListNode* Clone(RandomListNode* pHead)
{
RandomListNode* pCopy;
MAP hashNode;
pCopy=CloneNextNode(pHead,hashNode);
setRandomNode(pHead,pCopy,hashNode);
return pCopy;
}
};
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
CloneNodes(pHead);
CloneRandom(pHead);
return ReConnectNodes(pHead);
} void CloneNodes(RandomListNode* pHead){
RandomListNode* pCloned;
while(pHead!=NULL){
pCloned=new RandomListNode(pHead->label);
pCloned->next=pHead->next;
pHead->next=pCloned;
pHead=pCloned->next;
}
} void CloneRandom(RandomListNode* pHead){
RandomListNode* pCloned;
while(pHead!=NULL){
pCloned=pHead->next;
if(pHead->random!=NULL){
pCloned->random=pHead->random->next;
}
pHead=pCloned->next;
}
} RandomListNode* ReConnectNodes(RandomListNode* pHead){
RandomListNode* pClonedHead=NULL;
RandomListNode* pClonedNode=NULL;
RandomListNode* pNode=pHead; if(pNode!=NULL){
pClonedHead=pClonedNode=pNode->next;
pNode->next=pClonedNode->next;
pNode=pNode->next;
} while(pNode!=NULL){
pClonedNode->next=pNode->next;
pClonedNode=pClonedNode->next;
pNode->next=pClonedNode->next;
pNode=pNode->next;
}
return pClonedHead;
}
};
(剑指Offer)面试题26:复杂链表的复制的更多相关文章
- 剑指offer 面试题35.复杂链表的复制
时间O(N),空间O(N) /* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomList ...
- 剑指offer面试题26-复杂链表的复制
题目: 请实现函数ComplexListNode* Clone(ComplexListNode* pHead).复制一个复杂链表. 在复杂链表中.每个节点除了一个m_pNext指针指向下一个节点外,另 ...
- 剑指Offer - 九度1524 - 复杂链表的复制
剑指Offer - 九度1524 - 复杂链表的复制2014-02-07 01:30 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点 ...
- 剑指Offer面试题:14.链表的倒数第k个节点
PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...
- 剑指offer面试题26:复杂链表的复制
题目:请实现一个函数,复制一个复杂链表. 在复杂链表中,每个结点除了有一个next指针指向下一个结点外,还有一个sibling指针指向链表中的任意结点或者nulL 直观解法: 1.遍历链表,复制链表节 ...
- 剑指Offer:面试题26——复制复杂的链表(java实现)
问题描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 思路1: 1.先复制链表节点,并用next链接起来. 2.然后对每一个结点去修改 ...
- 剑指Offer:面试题16——反转链表(java实现)
问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = n ...
- 【剑指offer 面试题15】链表中倒数第K个结点
思路: 定义两个指针同时指向head,第一个指针先走K-1步,随后二个指针同时移动,当第一个指针到末尾处时,第二个指针所指向的即为倒数第K个结点. #include <iostream> ...
- 剑指offer面试题15:链表中倒数第K个节点
题目:输入一个链表,输出该链表的倒数第K个节点.为了符合大多数人的习惯,本题从1开始计数,即链表尾节点是倒数第一个节点. 解题思路: 解法一:一般情况下,单向链表无法从后一个节点获取到它前面的节点,可 ...
- 剑指offer——面试题23:链表中环的入口节点
函数: ListNode* MeetingNode(ListNode* pHead) { if(pHead==nullptr) return nullptr; ListNode* quickNode= ...
随机推荐
- 【转】Github轻松上手3-使用Tower图形化界面工具创建和管理repo
转自:http://blog.sina.com.cn/s/blog_4b55f6860100zzib.html 除了在命令行中输入特定的命令,另外一种方式就是用第三方的可视化工具,比如Mac下的Tow ...
- python numpy sum函数用法
numpy.sum numpy.sum(a, axis=None, dtype=None, out=None, keepdims=False)[source] Sum of array element ...
- Delphi RxRichEdit高级操作
unit InsertRichEditUnit;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, For ...
- selenium python (十一)alert/confirm/prompt的处理(js中的弹出框)
webdriver中处理js所生成的alert.confirm以及prompt,采用switch_to_alert()方法定位到alert/confirm/prompt.然后使用text/accept ...
- 序列for循环语句
序列for循环语句 序列for循环语句允许重复遍历一组序列,而这组序列可以是任何可以重复遍历的序列,如由begin()和end()函数定义的STL序列.所有的标准容器都可用作这种序列,同时它也同样可以 ...
- Window nginx+tomcat+https部署方案 支持ios9
客户端和 Nginx 之间走的 HTTPS 通讯,而 Nginx 到 Tomcat 通过 proxy_pass 走的是普通 HTTP 连接. 下面是详细的配置(Nginx 端口 80/443,Tomc ...
- java 抽象类和接口
接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 抽象类与接口是java语言中对抽象概念进行定义的两种机制,正是由于他们的存在才赋予java强大的面向对象的能力.他们两者之间对抽象概念 ...
- AI教程
AI制作铅笔图案笔刷 在下面的步骤中,我们将学习如何在Adobe Illustrator中创建铅笔笔刷.首先你要建立一个简单的网格,以及如何使用基本的工具和形状创建主要的形状.然后,学习如何保 ...
- WinForm 中两个窗口之间传递数据
方法有很多种,这里介绍项目中使用的两种 一.通过委托+事件的方法进行传值 (点击Form2中的button1按钮,将会把Form2中的textbox.text 传给Form1中的 lable.text ...
- 2013年19个最棒的HTML5网站模板免费下载
上次我们整理了14个HTML5奉献给大家下载了,今天我再给大家整理了19个2013最新的HTML5模板供有需要的朋友下载使用,它们涉及不同的行业的模板需求,支持手机设备,十分精美! 1. Affini ...