劍指offer:複雜鏈表的複製(java)

題目:請實現函數ComplexListNode複製一個複雜鏈表。在複雜鏈表中,每個結點除了有一個m_pNext指針指向下一個結點外,還有一個m_pSibling指向鏈表中的任意結點或者NULL;

   下圖是一個含有5個結點的該類型複雜鏈表。圖中實線箭頭表示m_pNext指針,虛線箭頭表示m_pSibling指針。爲簡單起見,指向NULL的指針沒有畫出。

                  程序員面試題精選100題(49)-複雜鏈表的複製 - 何海濤 - 微軟、Google等面試題

    看到這個問題,我的第一反應是分成兩步:第一步是複製原始鏈表上的每個鏈表,並用m_pNext鏈接起來。第二步,假設原始鏈表中的某節點Nm_pSibling指向結點S。由於S的位置在鏈表上有可能在N的前面也可能在N的後面,所以要定位N的位置我們需要從原始鏈表的頭結點開始找。假設從原始鏈表的頭結點開始經過s步找到結點S。那麼在複製鏈表上結點Nm_pSiblingS’,離複製鏈表的頭結點的距離也是s。用這種辦法我們就能爲複製鏈表上的每個結點設置m_pSibling了。

          對一個含有n個結點的鏈表,由於定位每個結點的m_pSibling,都需要從鏈表頭結點開始經過O(n)步才能找到,因此這種方法的總時間複雜度是O(n2)

           由於上述方法的時間主要花費在定位結點的m_pSibling上面,我們試着在這方面去做優化。我們還是分爲兩步:第一步仍然是複製原始鏈表上的每個結點N,並創建N’,然後把這些創建出來的結點鏈接起來。這裏我們對<NN’>的配對信息放到一個哈希表中。第二步還是設置複製鏈表上每個結點的m_pSibling。如果在原始鏈表中結點Nm_pSibling指向結點S,那麼在複製鏈表中,對應的N’應該指向S’。由於有了哈希表,我們可以用O(1)的時間根據S找到S’

           第二種方法相當於用空間換時間,以O(n)的空間消耗實現了O(n)的時間效率。

    接下來我們再換一種思路,在不用輔助空間的情況下實現O(n)的時間效率。第三種方法的第一步仍然是根據原始鏈表的每個結點N創建對應N。這一次,我們把N’鏈接到N的後面。

    第二步設置複製出來的結點的m_pSibling。假設原始鏈表上的N的m_pSibling指向結點S,那麼其對應複製出來的N'是m_pnext指向的結點,同樣S’也是S的m_pNext指向的結點。

    第三步把這個長鏈表拆分成兩個鏈表:把奇數位置的結點用m_pnext鏈接起來就是初始鏈表,把偶數位置的結點用m_pnext鏈接起來就是複製出來的鏈表。 

public class Solution {
    public ComplexListNode Clone(ComplexListNode pHead)
    {
        if(pHead == null){
            return null;
        }
        //複製接結點
        CloneNodes(pHead);

        //連接隨機指針
        ConnectSiblingNodes(pHead);

        //拆分鏈表
        return ReconnectNodes(pHead);

    }
    public static void CloneNodes(ComplexListNode pHead){
        ComplexListNode pNode = pHead;
        while(pNode != null){
            ComplexListNode pCloned = new ComplexListNode(pNode.label);
            pCloned.m_pnext = pNode.m_pnext;
            pCloned.m_pSibling = null;

            pNode.m_pnext = pCloned;
            pNode = pCloned.m_pnext;
        }


    }
    public static void ConnectSiblingNodes(ComplexListNode pHead){
        RandomListNode pNode = pHead;
        while(pNode != null){
            ComplexListNode pCloned = pNode.m_pnext;
            if(pNode.m_pSibling != null){
                pCloned.m_pSibling = pNode.m_Sibling.m_pnext;
            }

            pNode = pCloned.m_pnext;
        }
    }
    public static 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_next = pNode.m_next;
            pClonedNode = pClonedNode.m_pnext;
            pNode.m_pnext = pClonedNode.m_pnext;
            pNode = pNode.m_pnext;
        }

        return pClonedHead;
    }
}




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