// 使用额外空间:使用hash表,key是老节点,value是新节点。
// 遍历老节点,并取出对应value新节点,然后获得老节点next,
// 再从hash表中找出老节点next的value,新节点next就是这个value。rand也是这样。
public static Node copyRandomList1(Node head) {
// key 老节点
// value 新节点
HashMap<Node, Node> map = new HashMap<Node, Node>();
Node cur = head;
while (cur != null) {
map.put(cur, new Node(cur.val));
cur = cur.next;
}
cur = head;
while (cur != null) {
// cur 老
// map.get(cur) 新
// 新.next -> cur.next克隆节点找到
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
cur = cur.next;
}
return map.get(head);
}
// 老节点挂在新节点的next,然后新节点next指向老节点next。然后循环一对一对的设置rand。
// 新节点的rand就是老节点的rand的next,最后新老链表分离。利用新节点的位置关系实现了一一对应。1→1'→2→2’
public static Node copyRandomList2(Node head) {
if (head == null) {
return null;
}
Node cur = head;
Node next = null;
// 1 -> 2 -> 3 -> null
// 1 -> 1' -> 2 -> 2' -> 3 -> 3'
while (cur != null) {
next = cur.next; // 保留当前节点后驱
cur.next = new Node(cur.val); // 当前节点后驱指向当前复制节点
cur.next.next = next;
cur = next;
}
cur = head;
Node copy = null;
// 1 1' 2 2' 3 3'
// 依次设置 1' 2' 3' random指针
while (cur != null) {
next = cur.next.next;
copy = cur.next;
// 当前节点的随机节点下一个就是复制节点的随机节点
copy.random = cur.random != null ? cur.random.next : null;
cur = next;
}
Node res = head.next;
cur = head;
// 老 新 混在一起,next方向上,random正确
// next方向上,把新老链表分离
while (cur != null) {
next = cur.next.next;
copy = cur.next;
cur.next = next;
copy.next = next != null ? next.next : null;
cur = next;
}
return res;
}