劍指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;
}
};