1. 程式人生 > 其它 >複製含有隨機指標節點的連結串列

複製含有隨機指標節點的連結串列

【題目】一種特殊的單鏈表節點類描述如下

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 :
 */


import
java.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 */