劍指 offer程式碼解析——面試題26複雜連結串列的複製
阿新 • • 發佈:2022-05-03
本題詳細解析均在程式碼註釋中:
/** * 題目:請複製一個複雜連結串列。每個結點除了有一個next指標指向下一個結點外,還有一個sibling指向連結串列中的任意一個結點。 * @author 大閒人柴毛毛 * @date 2016年3月16日 */ public class CopyLink { /** * 分析:複製單鏈表較為簡單,只需遍歷單鏈表,建立結點,同時將前後連個結點相繼連起來即可。 * 本題的難點在於:每個結點還有一個sibling域,指向連結串列的任意一個結點。 * 本題最直觀的思路有兩種: * 1.先複製單鏈表,然後再複製sibling域; * 2.在複製單鏈表的同時確定sibling域名。 * 第一種方法較為簡單,複製完單鏈表後需再次遍歷原連結串列, * 若當前結點的sibling域不為空,則從當前結點開始依次向後查詢sibling域指向的位置, * 我們可以用一個計數器count記錄當前結點與sibling域指向的結點直接的距離, * 然後在新連結串列中,以該結點為起點,向後走count步即為sibling域指向的結點。 * 這種方式由於每個結點都要依次向後查詢sibling指向的結點,因此時間複雜度為O(n^2)。 */ /** * 下面介紹一種巧妙的方法: * 首先複製每個結點,並將他們插入在原結點的後面,從而形成一條新的連結串列; * 然後遍歷連結串列,若當前結點a的sibling不為空,則將a的下一個結點b的sibling指向a.sibling的下一個結點; * 最後拆分連結串列:將奇數位連起來,偶數位連起來即可。 * 程式碼如下: */ /** * 複製複雜連結串列 * @param first 複雜連結串列的頭結點 * @return 返回複製後的複雜連結串列 */ static boolean result = true;//copyLink執行結果 public static <T> Node<T> copyLink(Node<T> first){ //若連結串列為空 if(first==null){ System.out.println("連結串列為空!"); result = false; return null; } //複製每個結點,並插入原結點之後 Node<T> p = first; while(p!=null){ //建立新結點 Node<T> node = new Node<T>(); node.data = p.data; //將新結點插入p之後 node.next = p.next; p.next = node; } //複製每個結點的sibling域 p = first; while(p!=null){ p.next.sibling = p.sibling.next; } //拆分連結串列 p = first; Node<T> q = p.next; Node<T> first_copy = q;//被複制連結串列的頭結點 while(q!=null){ p.next = q.next; p = q; q = q.next; } return first_copy; } /** * 綜上所述:上述方法只需掃描連結串列3次: * 1.第一遍複製每個結點,並依次插入結點的後面; * 2.第二遍複製每個結點的sibling域; * 3.第三次拆分連結串列。 * 因此,上述方式的時間複雜度為O(n) */ } /** * 複雜連結串列的一個結點 */ class Node<T>{ T data; Node<T> next; Node<T> sibling; }