本文參考自《劍指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),可以考慮使用哈希表。哈希表的應用要掌握。