题目:请实现函数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) {
}
};
指针的题真的要思考清楚了再动笔,另外循环中语句的先后顺序与循环条件的设置是有关系的,琢磨琢磨就会形成自己的一套不易出错的模式。
欢迎交流指导~