複製含有隨機指標節點的連結串列
阿新 • • 發佈:2021-08-11
【題目】一種特殊的單鏈表節點類描述如下
class Node{ int value; Node next; Node rand; Node(int val){ value = val; } }
rand指標是單鏈表節點結構中新增的指標,rand可能指向連結串列中的任意一個節點,也可能指向null。
給定一個由Node節點型別組成的無環單鏈表的頭節點head,請實現一個函式完成這個連結串列的複製,並返回複製的新連結串列的頭節點。
【要求】時間複雜度0(N),額外空間複雜度0(1)
解法:
一、利用額外空間 雜湊表
1、新建一個雜湊表,以老連結串列的Node為key,值為對應copy的Node
2、處理next指標
3、處理rand指標
二、不利用額外空間
1、生成克隆節點,放在老連結串列的下一個,然後克隆節點去竄上老連結串列的下一個
2、設定rand指標
把1和克隆的1單獨拿出來,通過1找出rand指標的指向的Node節點,Node.next就是克隆的Node,讓克隆出來的1的rand指標指向克隆出來的Node。依次類推
3、分離新老連結串列
程式碼
package Algorithms; /** * @author : zhang * @version : 1.0 * @date : Create in 2021/8/11 * @description : */ importjava.util.HashMap; public class CopyListWithRandom { public static class Node { public int value; public Node next; public Node rand; public Node(int data) { this.value = data; } } //筆試 額外空間 雜湊表 public static Node copyListWithRand1(Node head) { HashMap<Node, Node> map = new HashMap<Node, Node>(); Node cur = head; //1、迴圈往map中克隆Node,以老Node為key,value為對應copy的Node while (cur != null) { map.put(cur, new Node(cur.value)); cur = cur.next; } cur = head; //2、處理next指標與rand指標 while (cur != null) { //cur老 map.get(cur) 新 //cur.next為連結串列中Node的下一個節點, // 找出來作為key,在map中查詢的value就是新Node【map.get(cur).next)】的next所要指向的節點 map.get(cur).next = map.get(cur.next); map.get(cur).rand = map.get(cur.rand); cur = cur.next; } return map.get(head); } //面試:不利用額外空間 public static Node copyListWithRand2(Node head) { if (head == null) { return null; } Node cur = head; Node next = null; //1、 copy node and link to every node //例 【1 ->2 】 -> 【1 -> 1' -> 2 -> 2'】 while (cur != null) { next = cur.next; //next儲存cur的下一個節點 cur.next = new Node(cur.value); //cur的下一個Node指向新克隆的Node cur.next.next = next; //新克隆的Node的下一個節點指向next cur = next;//cur後移,然後重複以上操作 } cur = head; Node curCopy = null; //2、 set copy node rand while (cur != null) { next = cur.next.next; curCopy = cur.next; curCopy.rand = cur.rand != null ? cur.rand.next : null; cur = next; } Node res = head.next; cur = head; //3、 split while (cur != null) { next = cur.next.next; curCopy = cur.next; cur.next = next; curCopy.next = next != null ? next.next : null; cur = next; } return res; } public static void printRandLinkedList(Node head) { Node cur = head; System.out.print("order: "); while (cur != null) { System.out.print(cur.value + " "); cur = cur.next; } System.out.println(); cur = head; System.out.print("rand: "); while (cur != null) { System.out.print(cur.rand == null ? "- " : cur.rand.value + " "); cur = cur.next; } System.out.println(); } public static void main(String[] args) { Node head = new Node(1); head.next = new Node(2); head.next.next = new Node(3); head.next.next.next = new Node(4); head.next.next.next.next = new Node(5); head.next.next.next.next.next = new Node(6); head.rand = head.next.next.next.next.next; // 1 -> 6 head.next.rand = head.next.next.next.next.next; // 2 -> 6 head.next.next.rand = head.next.next.next.next; // 3 -> 5 head.next.next.next.rand = head.next.next; // 4 -> 3 head.next.next.next.next.rand = null; // 5 -> null head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4 System.out.println("原連結串列為:"); printRandLinkedList(head); Node res1 = copyListWithRand1(head); System.out.println("【方式1】copy的連結串列為:"); printRandLinkedList(res1); Node res2 = copyListWithRand2(head); System.out.println("【方式2】copy的連結串列為:"); printRandLinkedList(res2); System.out.println("原連結串列為:"); printRandLinkedList(head); } } /** * 原連結串列為: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 * 【方式1】copy的連結串列為: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 * 【方式2】copy的連結串列為: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 * 原連結串列為: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 */