題目:請實現函數ComplexListNode * Clone(ComplexListNode * pHead),複製一個複雜鏈表。在複雜鏈表中,每個結點除了有一個 m_pNext 指針指向下一個結點外,還有一個 m_pSibling 指向鏈表中的任意結點或者NULL。
複雜鏈表結構定義如下:
typedef struct Node{
int m_nValue;
struct Node *m_pNext;
struct Node *m_pSibling;
}ComplexListNode;
方法一:
過程分析:
1、第一步複製原始鏈表上的每一個結點,並用 m_pNext 鏈接起來;
2、第二步設置每個結點的 m_pSibling 指針。
規律總結:
1、由於 m_pSibling 指針可能指向任意位置,因此需要有一個臨時指針遍歷,當遍歷到的結點的數據 等於 m_pSibling 指針 指向的結點的數據,說明臨時指針指向的位置就是 新鏈表 m_pSibling 指針 的值。不過前提是 鏈表中沒有重複結點。
2、如有重複結點,則需要 記錄 臨時指針 走了多少步 纔到原 m_pSibling 指向的結點。然後複製鏈表也走這麼多步。
時間複雜度:O(n^2)
算法如下:
/* 複製新的鏈表,使用了遞歸 */
ComplexListNode* CloneNode_own(ComplexListNode *pHead)
{
if(NULL == pHead)
return pHead;
ComplexListNode *pCloned = new ComplexListNode;
pCloned->m_nValue = pHead->m_nValue;
pCloned->m_pSibling = NULL;
pCloned->m_pNext = CloneNode_own(pHead->m_pNext);
return pCloned;
}
/* 指定 m_pSibling,使用的是總結的規律1 */
ComplexListNode* ConnectSiblingNodes_own(ComplexListNode *pHead,ComplexListNode *pClonedHead)
{
if(NULL == pHead || NULL == pClonedHead)
return pClonedHead;
ComplexListNode *pNode = pHead;
ComplexListNode *pClonedNode = pClonedHead;
while(pClonedNode != NULL)
{
if(pNode->m_pSibling != NULL)
{
ComplexListNode *temp = pClonedHead; /**ComplexListNode *temp = pClonedNode; 不要這樣寫,因爲m_pSibling可能指向前面*/
while(temp->m_nValue != pNode->m_pSibling->m_nValue)
{
temp = temp->m_pNext;
}
pClonedNode->m_pSibling = temp;
}
pClonedNode = pClonedNode->m_pNext;
pNode = pNode->m_pNext; /**這一步不要忘*/
}
return pClonedHead;
}
方法二:
第一步:根據原始鏈表的每個結點 N 創建對應的 N' ,並且將 N' 接在 N 的後面。
第二步:設置複製出來的結點的 m_pSibling 。假設原始鏈表上的 N 的 m_pSibling 指向結點 S,那麼其對應賦值出來的 N' 是 N 的 m_pNext 指向的結點,同樣 S' 也是 S 的 m_pNext 指向的結點。
第三步:將兩個鏈表拆分成兩個鏈表。
時間複雜度:O(n)
算法如下:
/**第一步:複製原始鏈表的結點N並創建新結點N‘,再把N‘鏈接到N的後面*/
void CloneNodes(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->m_pNext;
}
}
/**第二步:設置賦值出來的結點的 m_pSibling */
void ConnectSiblingNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while(pNode != NULL)
{
ComplexListNode* pCloned = pNode->m_pNext;
if(pNode->m_pSibling != NULL)
{
pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
}
pNode = pCloned->m_pNext;
}
}
/**第三步:將長鏈表分割成兩個鏈表*/
ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
ComplexListNode* pClonedHead = NULL;
ComplexListNode* pClonedNode = 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);
}
總結:
這道題比較難理解,需要一步步分析,就比如方法二的第三步,需要有想象,一個拆線,連線的過程
/* 點滴積累,我的一小步 */