普通鏈表的節點定義以下:node
// Definition for a Node. class Node { int val; Node next; public Node(int val) { this.val = val; this.next = null; } }
本題鏈表的節點的定義以下
比普通的鏈表多了一個randomdom
// Definition for a Node. class Node { int val; Node next, random; public Node(int val) { this.val = val; this.next = null; this.random = null; } }
就是在複製鏈表的時候還要帶着random
這個時普通鏈表的複製this
class Solution { public Node copyRandomList(Node head) { Node cur = head; Node dum = new Node(0), pre = dum; while(cur != null) { Node node = new Node(cur.val); // 複製節點 cur pre.next = node; // 新鏈表的 前驅節點 -> 當前節點 // pre.random = "???"; // 新鏈表的 「 前驅節點 -> 當前節點 」 沒法肯定 cur = cur.next; // 遍歷下一節點 pre = node; // 保存當前新節點 } return dum.next; } }
HashMap 的鍵值對,構建原來的鏈表節點和新鏈表的對應節點的鍵值對映射關係,而後再遍歷next和random引用指向spa
也就是構建新的鏈表爲
node1→node1new→node2→node2 new→⋯
所以當node1指向node2的時候node1new也指向node2new,node1的random指向本身的random的時候,那node1new的random也就只想node1.random.nextcode
/* // Definition for a Node. class Node { int val; Node next; Node random; public Node(int val) { this.val = val; this.next = null; this.random = null; } } */ class Solution { public Node copyRandomList(Node head) { if(head==null) return null; //首先定義舊鏈表的頭節點 Node cur = head; //複製各個節點構成拼接鏈表 while(cur!=null){ Node temp = new Node(cur.val); //新鏈表節點的next是當前節點的next temp.next = cur.next; //當前節點的next是新節點 cur.next = temp; //繼續便利,下一個節點應該是當前節點的next的next,也就是temp的next cur = temp.next; } //對新拼接的鏈表設置random指向 cur = head; while(cur!=null){ if(cur.random!=null){ //下一個節點也就是新節點的隨機等於當前舊節點的隨機的next cur.next.random = cur.random.next; } cur = cur.next.next; } //指向完畢 對鏈表進行拆分 直接拿頭節點的next就是新鏈表的頭節點 cur = head.next; Node res = head.next; Node pre = head; while(cur.next!=null){ pre.next = pre.next.next; cur.next = cur.next.next; pre = pre.next;//舊鏈表 cur = cur.next;//新鏈表 } //執行完畢以後,舊鏈表還差一個尾節點的next的null沒加 //由於他原本的next應該是新鏈表,可是拆開以後就變成null了 pre.next = null; return res; } }