本题有两种解法,分别为哈希表, 拼接与拆分
1. 哈希表
class Solution {
public Node copyRandomList(Node head) {
Node cur = head;
Map<Node,Node> map = new HashMap<>();
while(cur != null){
map.put(cur,new Node(cur.val));
cur = cur.next;
}
cur = head;
while(cur != null){
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
cur = cur.next;
}
return map.get(head);
}
}
利用哈希表的查询特点,考虑构建 原链表节点 和 新链表对应节点 的键值对映射关系,再遍历构建新链表各节点的 next
和 random
引用指向即可。
由于原结点与新结点之间存在映射关系,所以要找到新节点的next和random只需根据哈希表找到相应原结点的指针即可.
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
2. 拼接 + 拆分
考虑构建 原节点 1 -> 新节点 1 -> 原节点 2 -> 新节点 2 -> …… 的拼接链表,如此便可在访问原节点的 random 指向节点的同时找到新对应新节点的 random 指向节点。
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return null;
Node cur = head;
while(cur != null) {
Node tmp = new Node(cur.val);
tmp.next = cur.next;
cur.next = tmp;
cur = tmp.next;
}
cur = head;
while(cur != null) {
if(cur.random != null)
cur.next.random = cur.random.next;
cur = cur.next.next;
}
cur = head.next;
Node pre = head, res = head.next;
while(cur.next != null) {
pre.next = pre.next.next;
cur.next = cur.next.next;
pre = pre.next;
cur = cur.next;
}
pre.next = null;
return res;
}
}
总结
该题的核心其实是构建 原链表节点 和 新链表对应节点 的映射关系,只要有了映射关系我们就可以快速的找到新节点对应的原节点实现链表的复制,哈希表和拼接都可以实现映射关系的建立,哈希表的空间复杂度高于拼接。