複製含有隨機指針節點的鏈表
【 題目】 一種特殊的單鏈表節點類描述如下
class Node {
int value;
Node next;
Node rand;
Node(int val) {
value = val;}}
rand指針是單鏈表節點結構中新增的指針, rand可能指向鏈表中的任意一個節點, 也可能指向null。 給定一個由Node節點類型組成的無環單鏈表的頭節點head, 請實現一個函數完成這個鏈表的複製, 並返回複製的新鏈表的頭節點。
【 要求】 時間複雜度O(N), 額外空間複雜度O(1)
不考慮空間複雜度,
我們就利用哈希表,其實就是一個普通字典map
首先遍歷一遍,存好map。然後找1的next指針發現是2,然後把2的map對應的2‘給1’的next
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;
while (cur != null) {
map.put(cur, new Node(cur.value));//克隆節點給mapnew Node(cur.value)
cur = cur.next;
}
cur = head;
while (cur != null) {
map.get(cur).next = map.get(cur.next);//新節點的當前的next = 原先的next指向的克隆map節點
map.get(cur).rand = map.get(cur.rand);
cur = cur.next;
}
return map.get(head);//返回頭結點的克隆節點
}
考慮空間複雜度:不用map
利用結構的設計,將map替代
成對設計
成對兒取出,
這樣的設計,新節點的next指針就是下下一個node(注意邊界),新節點的rand指針就是上一個節點的rand指針的next的node。
1‘的next指針很好找,rand指針,因爲1的rand指針是3,所以1’克隆指針就是3的next。
public static Node copyListWithRand2(Node head) {
if (head == null) {
return null;
}
// 成對設計
Node cur = head;//當前 節點 初始化 到頭結點
Node next = null;
// copy node and link to every node
// 1_>2
// 1_>1'_>2
while (cur != null) {
next = cur.next;//記錄後面的環境 2
cur.next = new Node(cur.value);//當前節點的下一個就是克隆的節點
cur.next.next = next;//當前節點的下下一個,是原先的next 2
cur = next;//走向下一個節點 2
}
cur = head;
Node curCopy = null;//curCopy就是新節點
// set copy node rand
// 1——1'——2-2’
// 成對取出
while (cur != null) {
next = cur.next.next;//記錄的下一次的開始的位置,因爲成對取出,所以是後後的環境 2,
curCopy = cur.next;//拷貝的數據本身data是1'
curCopy.rand = cur.rand != null ? cur.rand.next : null;
cur = next;
}
Node res = head.next;
cur = head;
// split 老鏈表鏈接好,新聯表連接好 重新鏈接next指針
while (cur != null) {
next = cur.next.next;//成對遍歷
curCopy = cur.next;
cur.next = next;
curCopy.next = next != null ? next.next : null;
cur = next;
}
return res;