1.题目
2.思路
自己琢磨的
读题理解了10来分钟才明白题目是啥意思,一开始想复制一个链表,返回一个链表,直接return head是不是就行了,系统提示没有改变元素,还是原来的,所以不行....
继续想,假如简化一点条件,不考虑random节点,是不是很好做,直接遍历一次,最开始new一个Node节点,然后移动赋值就可以。
那么有random节点的区别在哪儿呢?首先就是指向是随机的,所以没办法直接像给next赋值,并且有可能会指向前面的节点,或者后面的节点,此时后面的节点还没有初始化。所以感觉一次遍历行不通。那么就多遍历几次好了,时间复杂度依然是O(n)
第一次遍历:用一个哈希表记录下原来旧的节点的位置<Node, Integer>
第二次遍历: 除掉random指针,val 和 next 指针通通赋值。indexMap<Ineteger, Node>记录每一个位置的新复制的节点。
第三次遍历:通过两个哈希表的记录,找到每一个节点的random指针指向第几个元素, 然后执行这个索引的新节点,这样就不用担心这个节点还没赋值完。
撒时间复杂度-O(n) -- 1ms--看起来很绕!!!-50min
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
*/
class Solution {
public Node copyRandomList(Node head) {
if(head == null)
return null;
Node head1 = head;
Node head2 = head;
Map<Node, Integer>map = new HashMap();
int index = 0;
Node node = head2;
while(node != null){
// node
map.put(node, index);
// System.out.println(node.val +">>>");
index++;
node = node.next;
// head2 = head2.next;
}
// System.out.println(index);
Map<Integer, Node>indexMap = new HashMap(); //记录索引节点的value
Node head3 = new Node(-1);
Node tail3 = head3;
Node tail4 = head3;
int t = 0;
while(head != null){
int val = head.val;
Node next = head.next;
tail3.val = val;
if(next != null)
tail3.next = new Node(next.val);
tail3.random = null;
indexMap.put(t, tail3);
t++;
head = head.next;
tail3 = tail3.next;
}
while(head1 != null){
int i = map.getOrDefault(head1.random, -1);
if(i != - 1)
tail4.random = indexMap.get(i);
head1 = head1.next;
tail4 = tail4.next;
}
return head3;
}
}
官方答案-dfs+哈希表-0ms--太妙了
注意要考虑head == null
使用哈希表是为了重复创建新节点。
dfs()赋值一个节点的所有参数。
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
*/
class Solution {
Map<Node, Node>cacheMap = new HashMap();
public Node copyRandomList(Node head) {
return dfs(head);
}
// dfs -- 只需要考虑这一个节点的操作。
public Node dfs(Node head){
// 迭代
if(head == null) return null;
// 如果节点之前就已经被创建,那么直接从哈希表取出就行。
if(!cacheMap.containsKey(head)){
Node newNode = new Node(head.val);
cacheMap.put(head, newNode);
newNode.next = dfs(head.next);
newNode.random = dfs(head.random);
}
return cacheMap.get(head);
}
}
3.结果
4.收获
10min没思路,赶紧跳过,看题解,看看是算法的原因还是数据结构的原因还是理解题意。
链表的题通常仔细思考都能解决,注意是否需要设置哨兵节点dummy
注意思考时间复杂度