1. 程式人生 > >【Java】 劍指offer(35) 復雜鏈表的復制

【Java】 劍指offer(35) 復雜鏈表的復制

erl logs tex 註意 eno pyc 包含 span val

本文參考自《劍指offer》一書,代碼采用Java語言。

更多:《劍指Offer》Java實現合集

題目 

  請實現函數ComplexListNode* Clone(ComplexListNode* pHead),復制一個復雜鏈表。在復雜鏈表中,每個結點除了有一個m_pNext指針指向下一個點外,還有一個m_pSibling 指向鏈表中的任意結點或者nullptr。

思路

  思路1:先復制結點,用next鏈接,最後根據原始結點的sibling指針確定該sibling結點距離頭結點的位置,從而對復制結點設置sibling指針。但是該思路對於n個結點的鏈表,每個結點的sibling都需要O(n)個時間步才能找到,所以時間復雜度為O(n^2)

  思路2:復制原始結點N創建N’,用next鏈接。將<N,N‘>的配對信息存放入一個哈希表中;在設置sibling時,通過哈希表,只需要用O(1)的時間即可找到復制結點的sibling。該方法的時間復雜度為O(n),但空間復雜度為O(n)。

  思路3:復制原始結點N創建N’,將N‘鏈接到N的後面;根據原始結點N的sibling可以快速設置N‘結點的sibling,最後將這個長鏈表拆分成原始鏈表和復制鏈表(根據奇偶位置)

測試算例 

  1.功能測試(sibling指向自己;鏈表只有一個結點;sibling指向null或者指向結點)

  2.特殊測試(頭結點為null)

Java代碼

//題目:請實現函數ComplexListNode* Clone(ComplexListNode* pHead),復
//制一個復雜鏈表。在復雜鏈表中,每個結點除了有一個m_pNext指針指向下一個
//結點外,還有一個m_pSibling 指向鏈表中的任意結點或者nullptr。


public class CopyComplexList {
	public class ComplexListNode {
	    int val;
	    ComplexListNode next = null;
	    ComplexListNode sibling = null;

	    ComplexListNode(int label) {
	        this.val = label;
	    }
	}
	
	/*
	 * 主程序(包含三步)
	 */
	public ComplexListNode cloneList(ComplexListNode head) {
		cloneNodes(head);  			//1.復制結點
		connectSiblingNodes(head);  //2.設置sibling
		return reconnectNodes(head);//3.拆分長鏈表
	}
	
	/*
	 * 第一步:復制每個結點,並插入到原始節點的後面
	 */
	private void cloneNodes(ComplexListNode head) {
		ComplexListNode pNode=head;
		while(pNode!=null) {
			ComplexListNode clonedNode=new ComplexListNode(pNode.val);
			clonedNode.next=pNode.next;
			pNode.next=clonedNode;
			pNode=clonedNode.next;
		}
	}
	
	/*
	 * 第二步:根據原結點的sibling,設置復制結點的sibling
	 */
	private void connectSiblingNodes(ComplexListNode head) {
		ComplexListNode pNode=head;
		while(pNode!=null) {
			if(pNode.sibling!=null)	//必須考慮到siblingNode==null的情況!
				pNode.next.sibling=pNode.sibling.next;
			pNode=pNode.next.next;
		}
	}
	
	/*
	 * 第三步:將長鏈表拆分成原始鏈表和復制鏈表(根據奇偶位置)
	 */
	private ComplexListNode reconnectNodes(ComplexListNode head) {
		ComplexListNode clonedHead=null;
		ComplexListNode clonedNode=null;
		ComplexListNode pNode=head;
		if(head!=null) {
			clonedHead=head.next;
			clonedNode=pNode.next;
			pNode.next=clonedNode.next;
			pNode=pNode.next;	//提前將pNode指向下一個結點,方便判斷是否為null
		}
		while(pNode!=null) {
			clonedNode.next=pNode.next;
			clonedNode=clonedNode.next;
			pNode.next=clonedNode.next;
			pNode=pNode.next;
		}
		return clonedHead;
	}
}

  

收獲

  1.涉及鏈表結點操作,必須時刻註意對null的判斷

  2.復制鏈表時,在原始結點後面直接插入復制結點,這種方法非常方便,有較高的時間效率,先記住,以後可能會遇到類似的應用

  3.查找時間復雜度為O(1),可以考慮使用哈希表。哈希表的應用要掌握。

更多:《劍指Offer》Java實現合集

  

【Java】 劍指offer(35) 復雜鏈表的復制