(剑指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= ...
随机推荐
- Android GLSurfaceView用法详解(二)
输入如何处理 若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件.下面有个例子: java代码: package eoe.ClearTes ...
- 实用js+css多级树形展开效果导航菜单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- java事务的处理
java的事务处理,如果对数据库进行多次操作,每一次的执行或步骤都是一个事务. 如果数据库操作在某一步没有执行或出现异常而导致事务失败,这样有的事务被执行有的就没有被执行,从而就有了事务的回滚,取消先 ...
- Oracle 安装 检查操作系统版本 必须是 5.0 5.1 的解决办法
打开 oraparam.ini文件 添加红色部分 Windows=5.1,5.2,6.1 最下面添加 [Windows-6.1-required]#Minimum display colours fo ...
- HDU5812 Distance 构造,预处理
分析:怎么看都是超时,但是可以先筛一遍1e6以内的每个数的最小素数 算出每个数由多少个素数组成,然后应用,c[1e6][20] 就是题解的那一套,参照题解,比赛的时候没有想到好的办法筛一个数的因子,醉 ...
- dword word byte 相互转换 .xml
pre{ line-height:1; color:#800080; background-color:#d2c39b; font-size:16px;}.sysFunc{color:#627cf6; ...
- Android的主要组件
(一)Activity(活动) 作用:提供可视化用户界面 只能通过setContentView(View)来显示指定组件 View组件是所有UI控件.容器控件的基类,View组件就是android应用 ...
- Spring框架入门:(非原著,转载)
1.1. 耦合性和控制反转: 对象之间的耦合性就是对象之间的依赖性.对象之间的耦合越高,维护成本越高.因此,对象的设计应使类和构件之间的耦合最小. 例: public interface I ...
- 2014搜狗前端面经【A事业部】
刚刚面完搜狗,有种莫名其妙的感觉,哪里莫名其妙呢?听我慢慢道来... 开始面试官就这简历,问了一些有的没的东西,都不深(好吧我承认之前的经历有点菜,没神马加分项啊). 后面开始技术面: 知识点1:JS ...
- Hive常用命令
本位为转载,原地址为:http://www.cnblogs.com/BlueBreeze/p/4232421.html #创建新表 hive> CREATE TABLE t_hive (a in ...