剑指offer——25.复杂链表的复制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/N1neDing/article/details/83042059

题目描述:

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

解题思路1:

首先根据next节点复制一个原链表,先不考虑random指向

再根据原链表每个节点,找到指向random的位置和首节点之间的距离,在复制链表中相同位置节点,random指向距离复制链表首节点相同距离位置的节点

如:原链表:next:1->2->3,random:1->3,2->3

首先根据next复制一个链表:1->2->3,然后发现1的random3指向距离首节点之后的两个距离的位置,则在复制的链表中1的random也指向首节点之后的两个的位置3,对所有节点相同处理。

这种思路较容易想到,但是时间复杂度为o(n^2),且实现起来很繁琐

解题思路2:

还是首先根据next复制一个链表,然后将原链表与复制链表的相同位置的节点构建一个map序列

如:原链表:next:a->b->c->d,random:a->c,b->d,c->d,d->NULL

根据next新建链表:a'->b'->c'->d',unordered_map<RandomListNode*,RandomListNode*>插入四个对,反别为(a,a'),(b,b'),(c,c'),(d,d')

则a‘的random指向为a的random指向c的map中的value,时间复杂度变为O(n)

参考源码:

class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {  
            if(pHead == NULL) return NULL;
            unordered_map<RandomListNode*,RandomListNode*> pir;
            RandomListNode* newhead = new RandomListNode(pHead->label);
            pir.insert(make_pair(pHead,newhead));
            RandomListNode* tmpbf = pHead->next;
            RandomListNode* tmp = newhead;
            while(tmpbf != NULL)
            {
                    RandomListNode* node = new RandomListNode(tmpbf->label);
                    pir.insert(make_pair(tmpbf,node));
                    tmp->next = node;
                    tmp = tmp->next;
                    tmpbf = tmpbf->next;
            }
            RandomListNode* t = pHead;
            while(t != NULL)
            {
                    pir[t]->random = pir[t->random];
                    t = t->next;
            }
            return newhead;
    }  
};

解题思路3:

首先将原链表所有节点复制一个到节点之后:a->b->c,复制后为a->a->b->b->c->c

然后将所有节点node进行:node->next->random = node->random->next的操作,则可以将所有复制的节点指向正确的复制的random节点

再将原链表和复制链表拆分,返回复制链表的头。

注意:当涉及->next->next双指针时,一定注意->next为空的判断情况,否则会发生指针错误(当node->next为空再指向node->next->next时)

参考源码:

class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {  
            if(pHead == NULL) return NULL;
            RandomListNode* headbf = pHead;
            //将所有节点复制
            while(headbf != NULL)
            {
                    RandomListNode* t = headbf->next;
                    RandomListNode* tmp = new RandomListNode(headbf->label);
                    headbf->next = tmp;
                    tmp->next = t;
                    headbf = headbf->next->next;
            }
            //将所有复制的节点random指向正确位置
            RandomListNode* headbf1 = pHead;
            while(headbf1 != NULL)
            {
                    if(headbf1->random != NULL)
                    {
                        headbf1->next->random = headbf1->random->next;
                    }
                    headbf1 = headbf1->next->next;
            }
            //将原链表和新链表分开
            RandomListNode* newhead = pHead->next;
            RandomListNode* tmp = pHead;
            while(tmp->next != NULL)
            {
                    RandomListNode* t = tmp->next;
                    tmp->next = t->next;
                    tmp = t;
            }
            return newhead;
    }  
};

猜你喜欢

转载自blog.csdn.net/N1neDing/article/details/83042059
今日推荐