題目描述
輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)
概念
複雜鏈表示例:方法一
可以分爲兩步來完成:
1、複製原始鏈表上的每一個結點,並用next鏈接起來;
2、設置每個結點的random 指針:由於鏈表中節點的random指針指向的節點可能在該節點之前,也可能在該節點之後,需要從頭到尾的遍歷鏈表來進行查找,然後連接起來,所以時間複雜度是O(N^2)。
方法二
方法一的時間花費主要在定位結點的random上,故我們可以對此優化:用空間換時間。方法還是可以分爲兩步:
1、複製原始鏈表上的每一個結點,並用next鏈接起來,同時創建一個map映射表:<N,N'>(原始結點,複製的結點),將兩個鏈表中的節點映射起來,從而便於後續random指針的設置。
2、設置每個結點的random 指針:由於已經使用map結構將兩個鏈表中的節點進行了映射,可以很方便的找到random指針應該指向的節點。用O(n)的空間消耗把時間複雜度由O(N^2)降到了O(n)。
對應的代碼如下:
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if( pHead == NULL )
return NULL;
unordered_map<RandomListNode*,RandomListNode*> record;
RandomListNode* res = new RandomListNode(pHead->label);
RandomListNode* p1 = pHead->next;
RandomListNode* p2 = res;
while( p1 )
{
RandomListNode* temp = new RandomListNode(p1->label);
p2->next = temp;
record.insert( make_pair(p1,temp) );
p1 = p1->next;
p2 = temp;
}
p1 = pHead;
p2 = res;
while( p1 )
{
if( p1->random )
p2->random = record[p1->random];
p1 = p1->next;
p2 = p2->next;
}
return res;
}
};
方法三
方法可以分爲三步,以下圖中的鏈表爲例:
1、複製原始鏈表上的每一個結點N,創建對應的N’,並把N’放在N之後。如下圖:
2、設置每個結點的random 指針。如果原始鏈表上的結點N的random指向S,則對應的複製結點N’(即節點N的next)的random指向S’(節點S的next)。如下圖:
3、將長鏈表拆分成兩個鏈表:把奇數位置的結點用pNext連接起來的就是原始鏈表,把偶數位置的結點通過pNext連接起來的就是複製鏈表。
代碼如下:
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if( pHead == NULL )
return NULL;
RandomListNode* p = pHead;
while( p ) //複製每個節點
{
RandomListNode* temp = new RandomListNode(p->label);
temp->next = p->next;
p->next = temp;
p = temp->next;
}
p = pHead;
while( p ) //設置random指針
{
if( p->random )
p->next->random = p->random->next;
p = p->next->next;
}
p = pHead;
RandomListNode* res = pHead->next;
while( p ) //拆分
{
RandomListNode* n = p->next;
p->next = n->next;
if( n->next )
n->next = n->next->next;
p = p->next;
}
return res;
}
};