您的位置:首页 > Web前端

剑指offer(14)-复杂链表的复制

2016-11-11 18:41 381 查看
题目:

输入一个复杂链表(每个结点中有结点值,以及两个指针,一个指向下一个结点,另一个特殊指针指向任意一个结点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的结点引用,否则判题程序会直接返回空)

结点定义如下:

struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};


1.直接进行递归赋值,只是效率不高:

class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if (pHead == NULL)
return pHead;
RandomListNode *pClone = new RandomListNode(0);
pClone->next = pHead->next;
pClone->label = pHead->label;
pClone->random = pHead->random;
pClone->next = Clone(pHead->next);

return pClone;
}
};


2.采用书中讲述的哈希算法,以空间换取时间。

class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{

if(pHead == NULL)
return pHead;

//定义一个哈希表
unordered_multimap<RandomListNode*,RandomListNode*> table;

// 开辟一个头结点
RandomListNode* pClonedHead = new RandomListNode(pHead->label);
pClonedHead->next = NULL;
pClonedHead->random = NULL;

// 将头结点放入map中
table.insert(make_pair(pHead,pClonedHead));

//设置操作指针
RandomListNode* pNode=pHead->next;
RandomListNode* pClonedNode = pClonedHead;

// 复制结点并连接
while(pNode != NULL)
{
// 不断开辟pNode的拷贝结点
RandomListNode* pClonedTail = new RandomListNode(pNode->label);
pClonedTail->next = NULL;
pClonedTail->random = NULL;

//连接新结点,更新当前结点
pClonedNode->next = pClonedTail;
pClonedNode = pClonedTail;

//将对应关系  插入到哈希表中
table.insert(make_pair(pNode,pClonedTail));

//向后移动操作结点
pNode = pNode->next;
}

//需从头开始设置random结点,设置操作指针
pNode = pHead;
pClonedNode = pClonedHead;

// 根据map中保存的数据,找到对应的结点
while(pNode != NULL)
{

if(pNode->random != NULL)
{
//找到对应结点,更新复制链表
pClonedNode->random = table.find(pNode->random)->second;
}

//向后移动操作结点
pNode = pNode->next;
pClonedNode = pClonedNode->next;
}

return pClonedHead;
}
};


3.书中给出了高效的算法,复杂度为O(n),不需要额外空间。

class Solution {
public:
//复制原始链表的任一结点N并创建新结点N',再把N'链接到N的后边
void CloneNodes(RandomListNode* pHead)
{
RandomListNode* pNode=pHead;
while(pNode!=NULL)
{
RandomListNode* pCloned=new RandomListNode(0);
pCloned->label=pNode->label;
pCloned->next=pNode->next;
pCloned->random=NULL;

pNode->next=pCloned;

pNode=pCloned->next;
}
}
//如果原始链表上的结点N的random指向S,则对应的复制结点N'的random指向S的下一个结点S'
void ConnectRandomNodes(RandomListNode* pHead)
{
RandomListNode* pNode=pHead;
while(pNode!=NULL)
{
RandomListNode* pCloned=pNode->next;
if(pNode->random!=NULL)
pCloned->random=pNode->random->next;
pNode=pCloned->next;
}
}
//把得到的链表拆成两个链表,奇数位置上的结点组成原始链表,偶数位置上的结点组成复制出来的链表
RandomListNode* ReConnectNodes(RandomListNode* pHead)
{
RandomListNode* pNode=pHead;
RandomListNode* pClonedHead=NULL;
RandomListNode* pClonedNode=NULL;

//初始化
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;

}
//三步合一
RandomListNode* Clone(RandomListNode* pHead)
{
CloneNodes(pHead);
ConnectRandomNodes(pHead);
return ReConnectNodes(pHead);

}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: