剑指offer:复杂链表的复制

题目:请实现函数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) {
        }
};

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

欢迎交流指导~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值