1. 程式人生 > >劍指offer——24.複雜連結串列的複製

劍指offer——24.複雜連結串列的複製

題目描述:

輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的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;
    }  
};