思路:
方法一:使用哈希表
方法二:原地修改
代码:
方法一:
/*
// 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 cur=new Node(0);
cur=head;
Map<Node,Node> map=new HashMap<>();
//将节点index一一对应加入哈希表中
while(cur!=null){
//一一创建零散的node
map.put(cur,new Node(cur.val));
cur=cur.next;
}
cur=head;
while(cur!=null){
//先把一一创建的node节点连上
map.get(cur).next=map.get(cur.next);
map.get(cur).random=map.get(cur.random);
cur=cur.next;
}
return map.get(head);
}
}
方法二:
/*
// 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;
}
//这里是cur表示的是head
Node cur=head;
//1.构建辅助链表
while(cur!=null){
//这里是新节点,只是与cur一样,本质是2个,上面是同一个
Node temp=new Node(cur.val);
temp.next=cur.next;
cur.next=temp;
cur=temp.next;
}
//2.构建next与random
cur=head;
while(cur!=null){
if(cur.random!=null){
cur.next.random=cur.random.next;
}
//这里是2个next
cur=cur.next.next;
}
Node pre=head,res=head.next;
cur=head.next;
//2.拆分两链表
//这里的终止条件是cur.next
while(cur.next!=null){
//注意一下下面的顺序,先pre后cur
pre.next=pre.next.next;
cur.next=cur.next.next;
//这里是1个next
pre=pre.next;
cur=cur.next;
}
//单独处理原链表的尾节点为null
pre.next=null;
return res;
}
}
分解:
1)本题与一般题目的区别是增加了一个random
2)方法一:
i)第一次循环:将节点index一一对应加入哈希表中,每一个节点都是零散的Node
ii)第二次循环:把零散的Node节点连上
map.get(cur).next=map.get(cur.next);
map.get(cur).random=map.get(cur.random);
最后得出最终的答案:map.get(head)
3)方法二:
i)第一次循环:将每个节点复制一份放在该节点后方
cur=temp.next是将cur的指针传到temp的下一个,并不是改变cur的值
Node temp=new Node(cur.val);
temp.next=cur.next;
cur.next=temp;
cur=temp.next;
ii)第二次循环:构建next与random
cur.next.random=cur.random.next;
iii)第三次循环:拆分两个链表
1.注意终止条件是cur.next
2.后面pre.next=null是单独处理原链表的尾节点,设为null
3.最后返回head.next,也就是第二条链表的第一个节点
4.注意pre与cur的顺序,pre先。因为cur是终止条件
while(cur.next!=null){
//注意一下下面的顺序,先pre后cur
pre.next=pre.next.next;
cur.next=cur.next.next;
//这里是1个next
pre=pre.next;
cur=cur.next;
}
//单独处理原链表的尾节点为null
pre.next=null;
return res;
Node temp=new Node(cur.val)和Node cur=head的区别:
前者本质上temp和cur指向的节点是2个节点,只是值一样
后者cur是head的指针,本质是指向一个地方
复杂度分析:
方法一:
时间复杂度:O(N) 循环遍历O(2N)次
空间复杂度:O(N)利用了哈希表额外空间,哈希表里存储了N个元素
(返回Node是一定要的空间,但创建哈希表不是一定的)
方法二:
时间复杂度:O(N)循环遍历了O(3N)次
空间复杂度:O(1)原地修改,只使用了常量指针pre,cur,res等存储