一刷劍指offer(26)——複雜鏈表的複製

題目:
請實現函數ComplexListNode* Clone(ComplexListNode* pHead),複製一個複雜鏈表。在複雜鏈表中,每個結點除了有一個m_pNext指針指向下一個結點外,還有一個m_pSibling指向鏈表中的任意結點或者NULL。結點定義如下:
struct ComplexListNode
{
    int    m_nValue;
    ComplexListNode*    m_p    Next;
    ComplexListNode*    m_pSibling;
};

該問題可以分成兩部分解決:

1、複製原始鏈表上每一個結點,並用m_pNext鏈接起來

2、設置每個結點的m_pSibling指針

假設原始鏈表中某個結點N的m_pSibling指向結點S,因爲S的位置無法確定,所以需要從原始鏈表頭結點沿着m_pNext開始遍歷,對於一個含有n個結點的鏈表,時間複雜度爲O(n^2)。

爲了進行優化,可以採用哈希表的方式。

依然分成兩步:

1、複製原始鏈表上的每個結點N創建N‘,然後把這些創建出來的結點用m_pNext鏈接起來,同時把<N,N'>的配對信息放到一個哈希表裏;

2、設置複製鏈表上每個結點的m_pSibling,如果原始鏈表中結點N的m_pSibling指向結點S,那麼在複製鏈表中,對應的N’指向S‘。由於哈希表,可以在O(1)的時間根據S找到S’。

上述方法相當於用空間換時間,對於含有n個結點的鏈表,需要一個O(n)大小的哈希表,也就是說以O(n)的空間消耗把時間複雜度由O(n^2)降低到了O(n)。

下面這種思路可以在不用輔助空間的情況下實現O(n)的時間效率。

1、根據原始鏈表的每個結點N創建對應N‘,將N’鏈接在N的後面。

void ClongNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode=pHead;
    while(pNode!=NULL)
    {
        ComplexListNode* pCloned=new ComplexListNode();
        pCloned->m_nValue=pNode->m_nValue;
        pCloned->m_pNext=pNode->m_pNext;
        pCloned->m_pSibling=NULL;
        pNode->m_pNext=pCloned;
        pNode=pCloned->pNext;
    }
}

2、設置複製出來的結點的m_pSibling。假設原始鏈表上的N的m_pSibling指向結點S,那麼其對應複製出來的N‘是N的m_pNext指向的結點,同樣S’也是S的m_pNext指向的結點。即如果N的m_pSibling指向S,那麼N‘的m_pSibling指向S'。

void ConnectSiblingNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode=pHead;
    while(pNode!=NULL)
    {
        ComplexListNode* pCloned=pNode->m_pNext;
        if(pNode0>m_pSibling!=NULL)
        {
            pCloned->m_pSibling=pNode->m_pSibling->m_pNext;
        }
        pNode=pCloned->m_pNext;
    }
}

3、將長鏈表拆分成兩個鏈表:將奇數位置的結點用m_pNext鏈接起來就是原始鏈表,把偶數位置的結點用m_pNext連接起來就是複製鏈表。

ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode=pHead;
    ComplexListNode* pClonedHead=NULL;
    ComplexListNode* pCloneNode=NULL;
    if(pNode!=NULL)
    {
        pClonedHead=pClonedNode=pNode->m_pNext;
        pNode->m_pNext=pClonedNode->m_pNext;
        pNode=pNode->m_pNext;
    }
    while(pNode!=NULL)
    {
        pClonedNode->m_pNext=pNode->m_pNext;
        pClonedNode=pClonedNode->m_pNext;
        pNode->m_pNext=pClonedNode->m_pNext;
        pNode=pNode->m_pNext;
    }
    return pClonedHead;
}
//將上面三步合起來
ComplexListNode* Clone(ComplexListNode* pHead)
{
    CloneNodes(pHead);
    ConnectSiblingNodes(pHead);
    return ReconnectNodes(pHead);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章