题目:

请实现函数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. Heritrix源码分析(十二) Heritrix的控制中心(大脑)CrawlController(一)(转)

    本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/650694 本博客已迁移到本人独立博客: http://www.yun5u.com/ ...

  2. 10g中HASH GROUP BY引起的临时表空间不足

    原本在9i上可以顺利完成的CTAS脚本,迁移到10g后运行总是报“ORA-1652: unable to extend temp segment by 128 in tablespace TS_HQY ...

  3. 《C和指针》读书笔记 第2章-基本概念

    原创文章,转载请注明出处:http://www.cnblogs.com/DayByDay/p/3936485.html

  4. Oracle 11g RAC oc4j/gsd Offline

    Oracle 11g RAC中,发现oc4j以及gsd服务都处于offline状态,这是Oracle 11g RAC默认情形.即便如此,并不影响数据库的使用,因为 oc4j 是用于WLM 的一个资源, ...

  5. 【模版消息】C#推送微信模版消息(Senparc.Weixin.MP.dll)

    定义的模版内容: {{first.DATA}} 商品名称:{{product.DATA}} 商品价格:{{price.DATA}} 购买时间:{{time.DATA}} {{remark.DATA}} ...

  6. GUID转换成16位字符串或19位数据(确保唯一)

    // <summary> /// 根据GUID获取16位的唯一字符串 /// </summary> /// <param name=\"guid\"& ...

  7. web医疗影像浏览demo及地址

    各种web影像浏览demo及地址1.WPACS http://demo.dayisheng.com 帐号密码 cc dd(http://demo.dayisheng.com/wpacs33.aspx? ...

  8. Effective java笔记6--异常

    充分发挥异常的优点,可以提高一个程序的可读性.可靠性和可维护性.如果使用不当的话,它们也会带来负面影响. 一.只针对不正常的条件才使用异常 先看一段代码: //Horrible abuse of ex ...

  9. HTTP长连接(Comet)实现方式示例

    昨天看了comet的介绍后,虽然大概知道了comet的原理,不过没实际用过还是不太清楚,于是今天又在网上翻了一下别的网友共享的comet实现http长连接的例子,在 Comet Server Push ...

  10. 如何配置仿真器DM8127+SEED-XDS560v2PLUS和连接不上的问题的解决

    1 根据配置焊接JTAG电路转接板.我用的是14pin的. 2 安装仿真器驱动.安装完如下图 我安装的时候没有自动装上,第一次显示问号,后来手动的. 3 设置ccs工程 4 最后调试是这个样子 5 查 ...