import java.util.*;
/**
*
* Source : https://oj.leetcode.com/problems/copy-list-with-random-pointer/
*
* A linked list is given such that each node contains an additional random pointer
* which could point to any node in the list or null.
*
* Return a deep copy of the list.
*/
public class CopyListWithRandomPointer {
/**
* 拷贝一个链表,链表的每个节点都有一个随即指针,指向链表中任意一个元素或者是null
*
* 建立一个hashmap,将已经复制过的节点放入map中
* 遍历链表,如果该节点的下一个节点cur -> next 已经在hashmap中,表示被复制过,直接连接在next上,否则新建一个节点连接
* 如果该节点的random节点已经在hashmap中,则直接连接到random上,否则新建一个
*
* @param head
* @return
*/
public RandomLinkedList copy (RandomLinkedList head) {
if (head == null) {
return null;
}
Map<RandomLinkedList, RandomLinkedList> map = new HashMap<RandomLinkedList, RandomLinkedList>();
RandomLinkedList p = head;
RandomLinkedList cloneNode = new RandomLinkedList(head.value);
map.put(head, cloneNode);
while (p != null) {
if (p.next != null) {
if (map.containsKey(p.next)) {
cloneNode.next = map.get(p.next);
} else {
RandomLinkedList newNode = new RandomLinkedList(p.next.value);
map.put(p.next, newNode);
cloneNode.next = newNode;
}
}
if (p.random != null) {
if (map.containsKey(p.random)) {
cloneNode.random = map.get(p.random);
} else {
RandomLinkedList newNode = new RandomLinkedList(p.random.value);
map.put(p.random, newNode);
cloneNode.next = newNode;}
}
p = p.next;
cloneNode = cloneNode.next;
}
return map.get(head);
}
private static RandomLinkedList createList (int[] arr) {
if (arr.length == 0) {
return null;
}
RandomLinkedList head = new RandomLinkedList(arr[0]);
RandomLinkedList last = head;
List<RandomLinkedList> list = new ArrayList<RandomLinkedList>(arr.length);
list.add(last);
for (int i = 1; i < arr.length; i++) {
RandomLinkedList node = new RandomLinkedList(arr[i]);
last.next = node;
last = node;
list.add(node);
}
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
int rand = Math.abs(random.nextInt()) % (arr.length+1);
if (rand != arr.length) {
list.get(i).random = list.get(rand);
}
}
return head;
}
private static void print (RandomLinkedList head) {
List<Integer> values = new ArrayList<Integer>();
List<String> list = new ArrayList<String>();
while (head != null) {
values.add(head.value);
if (head.random != null) {
list.add(head.value + " ---> " + head.random.value);
}
head = head.next;
}
list.add(0, Arrays.toString(values.toArray(new Integer[values.size()])));
System.out.println(Arrays.toString(list.toArray(new String[list.size()])));
System.out.println();
}
private static class RandomLinkedList {
int value;
RandomLinkedList random;
RandomLinkedList next;
public RandomLinkedList(int value) {
this.value = value;
}
}
public static void main(String[] args) {
CopyListWithRandomPointer copyListWithRandomList = new CopyListWithRandomPointer();
int[] arr = new int[]{1,2,3};
RandomLinkedList head = createList(arr);
print(head);
print(copyListWithRandomList.copy(head));
}
}