力扣138随机链表复制(最本质问题解决:random指针)
题目来源:
138. 随机链表的复制 - 力扣(LeetCode)
最本质问题
最本质问题就是, random指针的处理。
这题,如果想要不使用hashMap就会出现一下两种问题:
问题1:
random指针问题,新结点还不存在random的指针,random是随机指向整个新链表的角度。
问题2:
random指针的引用问题: 如何将random指向原引用变为指向复制链表呢?
背景:
一次遍历,创建新结点,去赋值val和next值给到新结点,就会出现无法赋值random的情况,因为出现了问题1,二次遍历赋值random会发现,出现问题2,ramdom是指向原引用的。
random第一次遍历肯定无法赋值,random是指向原结点的,新链表没建立就不存在random指针,random指针是整条链表的角度来看的。
问题解决
问题1解决:
通过多次遍历解决
问题2解决:
通过给结点绑定映射关系,就能知道哪个结点对应哪个结点,这样就算random引用了原结点,依旧可以通过映射关系来获取。
隐式映射:
a->a的复制结点A->b->B->c->C
通过将此链表分离就可以获得a->b->c and A->B->C
一个原引用的链表,一个复制的链表。
显示引用:
使用HashMap
代码
第一次遍历,创建新结点,生成映射关系,
第二次遍历,进行赋值,赋值的next和random引用的是对应映射关系中的random
/*
// 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;Map<Node, Node> nodeMap = new HashMap<>();Node curr = head;while(curr != null) {nodeMap.put(curr,new Node(curr.val));curr = curr.next;}curr = head;while(curr != null) {Node newNode = nodeMap.get(curr);newNode.next = nodeMap.get(curr.next);newNode.random = nodeMap.get(curr.random);curr = curr.next;}return nodeMap.get(head);}
}