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.
Solution 1:
这种方法很直观,先遍历链表一次,拷贝next节点,并将原节点与拷贝过后的复制节点的映射关系用hashmap保存起来。然后再遍历一次链表,通过读取hashmap的映射关系来更新复制节点的random节点。
public RandomListNode copyRandomList(RandomListNode head) {
Map<RandomListNode, RandomListNode> map = new HashMap<>();
RandomListNode dummy = new RandomListNode(0);
RandomListNode node = dummy, h = head;
while(head != null) {
RandomListNode copy = new RandomListNode(head.label);
map.put(head, copy);
node.next = copy;
node = node.next;
head = head.next;
}
node = dummy.next;
while(node != null) {
if(h.random != null) {
node.random = map.get(h.random);
}
h = h.next;
node = node.next;
}
return dummy.next;
}
时间和空间复杂度均为O(n)
Solution 2:
这个方法比较难想出来,不需要额外空间,不那么直观。直接上图比较好理解。分3步:
1,复制节点,并将拷贝后的节点放到原节点的后面。
2,更新所有拷贝节点的random节点:h.next.random = h.random.next。
3,将原链表与复制链表断开。
public RandomListNode copyRandomList(RandomListNode head) {
if(head == null) return null;
RandomListNode h = head;
while(h != null) {
RandomListNode copy = new RandomListNode(h.label);
RandomListNode next = h.next;
h.next = copy;
copy.next = next;
h = next;
}
h = head;
while(h != null) {
if(h.random != null)
h.next.random = h.random.next;
h = h.next.next;
}
h = head;
RandomListNode newHead = h.next;
while(h != null) {
RandomListNode copy = h.next;
h.next = copy.next;
h = h.next;
copy.next = h != null ? h.next : null;
}
return newHead;
}
Solution 3:
递归的方法更好理解:
Map<RandomListNode, RandomListNode> map = new HashMap<>();
public RandomListNode copyRandomList(RandomListNode head) {
if(head == null) return null;
RandomListNode copy = map.get(head);
if(copy == null) {
copy = new RandomListNode(head.label);
map.put(head, copy);
copy.next = copyRandomList(head.next);
copy.random = copyRandomList(head.random);
}
return copy;
}