题目:

请实现函数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:复杂链表的复制的更多相关文章

  1. 剑指offer 面试题35.复杂链表的复制

    时间O(N),空间O(N) /* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomList ...

  2. 剑指offer面试题26-复杂链表的复制

    题目: 请实现函数ComplexListNode* Clone(ComplexListNode* pHead).复制一个复杂链表. 在复杂链表中.每个节点除了一个m_pNext指针指向下一个节点外,另 ...

  3. 剑指Offer - 九度1524 - 复杂链表的复制

    剑指Offer - 九度1524 - 复杂链表的复制2014-02-07 01:30 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点 ...

  4. 剑指Offer面试题:14.链表的倒数第k个节点

    PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...

  5. 剑指offer面试题26:复杂链表的复制

    题目:请实现一个函数,复制一个复杂链表. 在复杂链表中,每个结点除了有一个next指针指向下一个结点外,还有一个sibling指针指向链表中的任意结点或者nulL 直观解法: 1.遍历链表,复制链表节 ...

  6. 剑指Offer:面试题26——复制复杂的链表(java实现)

    问题描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 思路1: 1.先复制链表节点,并用next链接起来. 2.然后对每一个结点去修改 ...

  7. 剑指Offer:面试题16——反转链表(java实现)

    问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = n ...

  8. 【剑指offer 面试题15】链表中倒数第K个结点

    思路: 定义两个指针同时指向head,第一个指针先走K-1步,随后二个指针同时移动,当第一个指针到末尾处时,第二个指针所指向的即为倒数第K个结点. #include <iostream> ...

  9. 剑指offer面试题15:链表中倒数第K个节点

    题目:输入一个链表,输出该链表的倒数第K个节点.为了符合大多数人的习惯,本题从1开始计数,即链表尾节点是倒数第一个节点. 解题思路: 解法一:一般情况下,单向链表无法从后一个节点获取到它前面的节点,可 ...

  10. 剑指offer——面试题23:链表中环的入口节点

    函数: ListNode* MeetingNode(ListNode* pHead) { if(pHead==nullptr) return nullptr; ListNode* quickNode= ...

随机推荐

  1. xsheell的下载安装初级使用

    1)关于Xshell 网上更多的资料里提到的SSH客户端是putty,因为简单.开源.免费.但是也正是由于功能过于简单,所以在这里推荐大家使用Xshell. Xshell最初并不能免费使用,而且也没有 ...

  2. Java反射基本玩法

    三个主要的反射类 Class反射对象描述类语义结构,可以从Class对象中获取构造函数.成员变量.方法类等元素的反射对象,并以编程的方式通过这些反射对象对目标类对象进行操作.这些反射对象类在java. ...

  3. JVM——类的加载过程

    附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...

  4. mips-linux-gnu-gcc

    (1) -lz -lrt -lm -lc都是什么库 libzlibrtlibmlibc然后google之压缩库(Z)实时库(real time)数学库(math)标准C库(C lib) 可以进入/li ...

  5. 502 Bad Gateway nginx 解决

    打开 /usr/local/php/etc/php-fpm.conf 调大以下两个参数(根据服务器实际情况,过大也不行) <value name=”max_children”>5120&l ...

  6. android定时三种方式

    一.采用Handler与线程的sleep(long)方法二.采用Handler的postDelayed(Runnable, long)方法三.采用Handler与timer及TimerTask结合的方 ...

  7. PHP QR CODE生成二维码

    用法: <?php include "./phpqrcode/phpqrcode.php"; $value="http://www.xxx.com"; $ ...

  8. 解读Cardinality Estimation<基数估计>算法(第一部分:基本概念)

    基数计数(cardinality counting)是实际应用中一种常见的计算场景,在数据分析.网络监控及数据库优化等领域都有相关需求.精确的基数计数算法由于种种原因,在面对大数据场景时往往力不从心, ...

  9. 32+激发灵感的HTML5/CSS3网页设计教程

      HTML5是寄托在HTML4基础上取得了的广泛成就.这不仅意味着你不必完全放弃现有的一些标记,而是可以借鉴,以加强 它. CSS3也以同样的方式在互联网内容的安排下,提供了它的柔韧性.CSS3是开 ...

  10. Windows Server 2003单网卡搭建VPN

    Windows Server 2003单网卡搭建VPN   1.打开[控制面板] --> [管理工具] --> [路由和远程访问] 2.鼠标右击你要管理的电脑 在弹出式菜单中选中[配置并启 ...