複雜鏈表的複製

題目描述
輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)

首先這道題可以在這裏進行算法測試:複雜鏈表的複製
定義一下算法描述的鏈表節點的數據結構:

public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}

算法其實並不複雜,但是要將其清楚且完整地表達並且實現出來,還是需要一定的時間與代碼功底。

認真分析之後,將問題分解,問題分解的好處就是,不要求算法能夠一蹴而就,並且一蹴而就的算法代碼實現會極大增加算法的實現難度。

所以通過分析,將算法分成如下3個步驟

(1). 第一步:首先拷貝出每個節點,由於鏈表是從頭到尾拷貝的,那麼後面的拷貝子節點還暫時沒有生成,所以我們就暫時僅僅拷貝單個節點,拷貝的子節點字段暫時不設置。等到完全拷貝之後,到第二部再進行設置。
在這裏插入圖片描述

private void cloneNodes(RandomListNode node){
   RandomListNode cur = node, clonedNode = null;
   while(cur != null){
       clonedNode = new RandomListNode(cur.label);
       clonedNode.next = cur.next;
       cur.next = clonedNode;
       cur = clonedNode.next;
   }
}

代碼很簡單,就是單純地在每個源鏈表節點中間拷貝一個節點插入進去即可。

(2). 第二步:補充拷貝後節點的完整性。即,設置每個拷貝的節點的子節點(即數據結構中的random字段)
在這裏插入圖片描述

private void connectSilblingNodes(RandomListNode node){
    RandomListNode cur = node, clonedNode = null;
    while(cur != null){
        clonedNode = cur.next;
        if(cur.random != null){
            clonedNode.random = cur.random.next;
        }
        cur = clonedNode.next;
    }
}

(3). 第3步:將整個鏈表拆成兩個鏈表,一個是源鏈表,一個是拷貝後的鏈表。
在這裏插入圖片描述

private RandomListNode reconnectNodes(RandomListNode node){
    RandomListNode cur = node;
    RandomListNode dummyHead = new RandomListNode(-1);
    RandomListNode clonedNode = dummyHead;
    while(cur != null){
        
        clonedNode.next = cur.next;
        clonedNode = clonedNode.next;
        
        cur.next = clonedNode.next;
        cur = cur.next;
    }
    return dummyHead.next;
}

這裏用到了設置虛擬頭節點技巧,這是一個亮點,其它沒啥技巧,很容易懂。

下面是整個運行通過測試的代碼:

public class Solution {
	// the algorithm entrance ... 
    public RandomListNode Clone(RandomListNode pHead) {
        cloneNodes(pHead);
        connectSilblingNodes(pHead);
        return reconnectNodes(pHead);
    }
    
    private void cloneNodes(RandomListNode node){
        // ... ignore
        // reference the article above 
    }
    
    private void connectSilblingNodes(RandomListNode node){
        // ... ignore
        // reference the article above 
    }
    
    private RandomListNode reconnectNodes(RandomListNode node){
        // ... ignore
        // reference the article above 
    }
    
}

更多

總的來說還是基本的鏈表操作,但是問題要分析清楚,問題分析清楚就簡單了。

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