思路1 :最简单的思路就是直接复制以next为一链的链表,在之后遍历原链表获取random的链表值,在复制链表上去从头到尾的寻找对应的random值。
举例:原链表的节点 A ,在复制链表上节点为 A’ ,A的random指向C,那么 A’ 节点的random也应该指向C‘,但是是A‘链表所在的C’,所以我们需要从头到尾的去寻找C’
这样时间复杂度就为O(n^2)
思路2:我们依旧直接复制原链表的next链,但是我们一边复制一遍存储,因为A节点对一个在复制链表中的节点是A’,所以我们用hashMap去存储,key为A,value为A’。那么我们想一下既然A的random为C,那么A‘对应的random为C’,所以我们就可以通过C直接定位到C‘。HashMap的查询速率几乎等于O(1)。
所以我们需要一个长为原链表长度 n 的的链表,也需要一个大小为 n 的hashMap来存储Key和Value。
所以使用了空间来换时间的思想
时间复杂度:O(n)
空间复杂度:O(n)
public static Node copyRandomList(Node head) {
if(head == null) return null;
HashMap<Node,Node> hashMap = new HashMap<>();
//当random为null时,复制链表中的random也为null
hashMap.put(null,null);
Node copytemp = new Node(123);
//先将原链表按next复制
Node temp = head;
Node copyhead = copytemp;
while(temp != null){
//边复制,边储存
copytemp.next = new Node(temp.val);
hashMap.put(temp,copytemp.next);
temp = temp.next;
copytemp = copytemp.next;
}
//再遍历原数组匹配random值
temp = head;
copytemp = copyhead.next;
while(temp != null){
copytemp.random = hashMap.get(temp.random);
temp = temp.next;
copytemp = copytemp.next;
}
return copyhead.next;
}
思路三:我们复制的节点直接在原链表上增加复制的节点。
例如 A -》B -》C
复制节点后变成 A -> A’ -> B -> B’ -> C -> C’
那么原链表的A节点random为C节点。那么A的复制节点A’是A的next,那么A’的random也应该为C’,那么C‘的位置就在C节点的后面。所以我们就可以通过A找到C,再通过C找到C’,这样就找到了A‘的random。
所以我们再给节点复制random值时,我们就可以访问原链表节点,
A.next.random = A.random.next;
最后我们把原链表和复制链表分离。偶数为原链表,奇数位新链表。
public static Node copyRandomList1(Node head) {
if(head == null) return null;
Node newHead = null;
//把复制的节点直接连接到当前节点的后面
// 例如 A -》B -》C
// 复制节点后变成 A -> A' -> B -> B' -> C -> C'
cloned(head);
findRandom(head);
return getNewHead(head);
//新链表提取出来
//a a' b b' c c' null
}
//复制
public static void cloned(Node head){
Node temp = head;
while(temp != null){
Node copyNode = new Node(temp.val);
copyNode.next = temp.next;
temp.next = copyNode;
temp = temp.next.next;
}
}
public static void findRandom(Node head){
//A.next.random = A.random.next;
while(head != null ) {
if(head.random != null){
head.next.random = head.random.next;
}
head = head.next.next;
}
}
public static Node getNewHead(Node head){
Node newHead = head.next;
Node temp = null;
while(head.next != null ){
temp = head.next;
head.next = head.next.next;
head = temp;
}
return newHead;
}