(劍指Offer)面試題26:復雜鏈表的復制


題目:

請實現函數ComplexListNode* Clone(ComplexListNode* pHead),復制一個復雜鏈表。

在復雜鏈表中,每個結點除了有一個pNext指針指向下一個結點之外,還有一個pSibling指向鏈表中的任意結點或者NULL。

結點的定義如下:

struct ComplexListNode{
    int val;
    ComplexListNode* pNext;
    ComplexListNode* pSibling;
};

思路:

方法1:

復制原始鏈表上的每一個結點,並通過pNext連接起來;然后再設置每個結點的pSibling指針。

假設原始鏈表中某個結點N的pSibling指針指向結點S,那么就需要從頭到尾遍歷查找結點S,如果從原始鏈表的頭指針開始,經過m步之后達到結點S,那么在復制鏈表中的結點N'的pSibling指針指向的結點也是距離復制鏈表s步的結點。通過這種辦法就可以為復制鏈表上的每個結點設置pSibling指針。

時間復雜度:O(N^2)

方法2:

方法1是通過鏈表查找來得到pSibling指針所指向的結點,實際上我們可以通過空間換取時間,將原始鏈表和復制鏈表的結點通過哈希表對應起來,這樣查找的時間就從O(N)變為O(1)。具體如下:

復制原始鏈表上的每個結點N創建N',然后把這些創建出來的結點用pNext連接起來。同時把<N,N'>的配對信息方法一個哈希表中;然后設置復制鏈表中的每個結點的pSibling指針,如果原始鏈表中結點N的pSibling指向結點S,那么在復制鏈表中,對應的N'應該指向S'。

時間復雜度:O(N)

方法3:

在不使用輔助空間的情況下實現O(N)的時間效率。

第一步:根據原始鏈表的每個結點N創建對應的N',然后將N‘通過pNext接到N的后面;

第二步:設置復制出來的結點的pSibling。假設原始鏈表上的N的pSibling指向結點S,那么其對應復制出來的N'是N->pNext指向的結點,同樣S'也是結點S->pNext指向的結點。

第三步:把長鏈表拆分成兩個鏈表,把奇數位置的結點用pNext連接起來的就是原始鏈表,把偶數位置的結點通過pNext連接起來的就是復制鏈表。

代碼:

1、Hash方法:

struct ComplexListNode{
    int val;
    ComplexListNode* pNext;
    ComplexListNode* pSibling;
    ComplexListNode():val(0),pNext(NULL),pSibling(NULL){};
};

typedef std::map<ComplexListNode*,ComplexListNode*> MAP;

ComplexListNode* CloneNodes(ComplexListNode* pHead,MAP &hashNode){
    ComplexListNode* pNode=new ComplexListNode();
    ComplexListNode* p=pNode;
    ComplexListNode* tmp;

    while(pHead!=NULL){
        tmp=new ComplexListNode();
        tmp->val=pHead->val;
        p->pNext=tmp;
        hashNode[pHead]=tmp;
        pHead=pHead->pNext;
        p=p->pNext;
    }
    return pNode->pNext;
}

void SetSiblings(ComplexListNode* pHead,ComplexListNode* pCopy,MAP &hashNode){
    while(pCopy!=NULL){
        pCopy->pSibling=hashNode[pHead->pSibling];
        pCopy=pCopy->pNext;
        pHead=pHead->pNext;
    }
}

ComplexListNode* ComplexListCopy(ComplexListNode* pHead){
    ComplexListNode* pCopy;
    MAP hashNode;
    pCopy=CloneNodes(pHead,hashNode);
    SetSiblings(pHead,pCopy,hashNode);
    return pCopy;
}

2、復制連接方法:

#include <iostream>

using namespace std;

struct ComplexListNode{
    int val;
    ComplexListNode* pNext;
    ComplexListNode* pSibling;
    ComplexListNode(int x):val(x),pNext(NULL),pSibling(NULL){};
};

void CloneNodes(ComplexListNode* pHead){
    ComplexListNode* pNode=pHead;
    ComplexListNode* pCloned;
    while(pNode!=NULL){
        pCloned=new ComplexListNode(pNode->val);
        pNode->pNext=pCloned;
        pCloned->pNext=pNode->pNext;
        pNode=pCloned->pNext;
    }
}

void ConnectSiblingNodes(ComplexListNode* pHead){
    ComplexListNode* pNode=pHead;
    ComplexListNode* pCloned;
    while(pNode!=NULL){
        pCloned=pNode->pNext;
        if(pNode->pSibling!=NULL){
            pCloned->pSibling=pNode->pSibling->pNext;
        }
        pNode=pCloned->pNext;
    }
}

ComplexListNode* ReconnectNodes(ComplexListNode* pHead){
    ComplexListNode* pNode=pHead;
    ComplexListNode* pClonedHead=NULL;
    ComplexListNode* pClonedNode=NULL;

    if(pNode!=NULL){
        pClonedHead=pClonedNode=pNode->pNext;
        pNode->pNext=pClonedNode->pNext;
        pNode=pNode->pNext;
    }
    while(pNode!=NULL){
        pClonedNode->pNext=pNode->pNext;
        pClonedNode=pClonedNode->pNext;
        pNode->pNext=pClonedNode->pNext;
        pNode=pNode->pNext;
    }
    return pClonedHead;
}

ComplexListNode* Clone(ComplexListNode* pHead){
    CloneNodes(pHead);
    ConnectSiblingNodes(pHead);
    return ReconnectNodes(pHead);
}

在線測試OJ:

http://www.nowcoder.com/books/coding-interviews/f836b2c43afc4b35ad6adc41ec941dba?rp=1

AC代碼:

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    typedef std::map<RandomListNode*,RandomListNode*> MAP;
    RandomListNode* CloneNextNode(RandomListNode* pHead,MAP &hashNode){
        RandomListNode* pCopy=new RandomListNode(0);
        RandomListNode* p=pCopy;
        RandomListNode* tmp;
        while(pHead!=NULL){
            tmp=new RandomListNode(pHead->label);
            p->next=tmp;
            hashNode[pHead]=tmp;
            p=p->next;
            pHead=pHead->next;
        }
        return pCopy->next;
    }

    void setRandomNode(RandomListNode* pHead,RandomListNode* pCopy,MAP &hashNode){
        while(pCopy!=NULL){
            pCopy->random=hashNode[pHead->random];
            pCopy=pCopy->next;
            pHead=pHead->next;
        }
    }

    RandomListNode* Clone(RandomListNode* pHead)
    {
        RandomListNode* pCopy;
        MAP hashNode;
        pCopy=CloneNextNode(pHead,hashNode);
        setRandomNode(pHead,pCopy,hashNode);
        return pCopy;
    }
};
/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        CloneNodes(pHead);
        CloneRandom(pHead);
        return ReConnectNodes(pHead);
    }
    
    void CloneNodes(RandomListNode* pHead){
        RandomListNode* pCloned;
        while(pHead!=NULL){
            pCloned=new RandomListNode(pHead->label);
            pCloned->next=pHead->next;
            pHead->next=pCloned;
            pHead=pCloned->next;
        }
    }
    
    void CloneRandom(RandomListNode* pHead){
        RandomListNode* pCloned;
        while(pHead!=NULL){
            pCloned=pHead->next;
            if(pHead->random!=NULL){
                pCloned->random=pHead->random->next;
            }
            pHead=pCloned->next;
        }
    }
    
    RandomListNode* ReConnectNodes(RandomListNode* pHead){
        RandomListNode* pClonedHead=NULL;
        RandomListNode* pClonedNode=NULL;
        RandomListNode* pNode=pHead;
        
        if(pNode!=NULL){
            pClonedHead=pClonedNode=pNode->next;
            pNode->next=pClonedNode->next;
            pNode=pNode->next;
        }
        
        while(pNode!=NULL){
            pClonedNode->next=pNode->next;
            pClonedNode=pClonedNode->next;
            pNode->next=pClonedNode->next;
            pNode=pNode->next;
        }
        return pClonedHead;
    }
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM