您的位置:首页 > Web前端

剑指offer:复杂链表的复制

2016-12-09 18:12 375 查看
题目:请实现函数complexListNode*Clone(ComplexListNode*pHead),

复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL.

复杂链表如图例:


我们对单链表的复制已经很清楚,因此很容易形成思路,先将链表整个复制,但是先将m_pSiling初始化为NULL(显然,我们在所有节点不全存在的时候是不能进行m_pSiling的设置的,因为它很有可能指向的结点现在并没有创建);有了第一步所有结点都存在时,我们可以根据原链表中当前结点和其m_pSiling指向结点的位置关系来设置该指针。

//第一步:实现next复制,使整个链表成型

//第二步:对每个结点,通过在源结点查找到random指针指向的是距离头结点第几个结点,

//那么复制的链表对应的结点的random也指向距头结点第几个结点

//复杂度是O(n)+o(n)*n

当然有更好的思路(来源于剑指offer)

//更好的思路是(特点:思路巧妙,相对复杂,实现也相对麻烦,复杂度低)

//第一步:复制(将A
复制在A的后面)

//第二步:设置random

//第三步:将A和A
分开

//复杂度:O(n)+O(1)*n+O(n)

(1)将复制链表每一个结点依附于源结点(极大的便利了m_pSiling的设置)



(2)设置m_pSiling



(3)拆分原链表和复制链表



其实大多数人一旦知道这种依附于源结点创建复制结点的想法后,其他的思路都会自然而来的,只是指针操作看似简单,还是要十分小心,考虑周到。

附代码:

class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
RandomListNode* mergeHead = copyAfter(pHead);
buildRandom(mergeHead);
RandomListNode*newHead = splitList(mergeHead);
return newHead;
}
private:
RandomListNode*copyAfter(RandomListNode*pHead){
//RandomListNode* pCopyHead = NULL;
if (pHead == NULL)
return NULL;
RandomListNode*p1 = pHead;
RandomListNode*p2;
//pCopyHead = p2;
///p2->next = p1->next;
//p1->next = p2;
//p1 = p2->next;
while (p1){
p2 = new RandomListNode(p1->label);
p2->next = p1->next;
p1->next = p2;
p1 = p2->next;
}
return pHead;
}

void buildRandom(RandomListNode* mergeHead){
if (mergeHead == NULL)
return;
RandomListNode*p1 = mergeHead;
RandomListNode*p2;
RandomListNode*pRandom;
while (p1){
p2 = p1->next;
pRandom = p1->random;
if (pRandom)//有空的情况
p2->random = pRandom->next;
p1 = p2->next;
}
}

RandomListNode* splitList(RandomListNode* mergeHead){
if (mergeHead == NULL)
return NULL;

RandomListNode*newHead;
RandomListNode*p2 = newHead = mergeHead->next;
RandomListNode*p1 = mergeHead;
p1->next = p2->next;
p1 = p1->next;
while (p1){
p2->next = p1->next;
p2 = p2->next;
p1->next = p2->next;
p1 = p1->next;
}
return newHead;
}

};


结点的结构体:

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


指针的题真的要思考清楚了再动笔,另外循环中语句的先后顺序与循环条件的设置是有关系的,琢磨琢磨就会形成自己的一套不易出错的模式。

欢迎交流指导~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 链表