剑指 Offer 35. 复杂链表的复制(❤❤)
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
解法一
回溯法+哈希表:
思路就是,random既然不好拷贝,那我就先把next解决了,再考虑random设置,next怎么解决,遍历原链表,遍历一个创建一个新节点,新节点全部放到hashmap中去,一直到最后一个的时候,所有节点都存在与hashmap中,这时候从最后一个设置random节点,判断对应原链表中的random在hashmap中有没有(这个时候已经是有了的),就直接从map中拿到这个节点设置为上一个节点的random。
class Solution {
Map<Node,Node> map = new HashMap();
public Node copyRandomList(Node head) {
if(head == null){
return head;
}
if(!map.containsKey(head)){
Node NodeNew = new Node(head.val);
map.put(head,NodeNew);
NodeNew.next = copyRandomList(head.next);
NodeNew.random = copyRandomList(head.random);
}
return map.get(head);
}
}
解法二
链表复制+拆分
思路就是,既然你要复制一个链表,那我就把每个节点复制一遍接在对应的节点后面,再把复制节点的random指针都指向原节点的指针,再把这个链表一拆就行了。
步骤:
- 添加节点,构造一个复制后的链表,比如A->B->C 复制之后就是A->A’->B->B’->C->C’
- 将A ’ B’ C’ 的random指针分别指向对应ABC节点的random指针指向的节点下一个(即复制过后的random,比如A的random指向C,那么这里复制过后的A’的random指向C->next,也就是C‘)
- 拆分链表,通过调整next指向将ABC A’B’C’拆分成两个链表,返回A’即可。
class Solution {
public Node copyRandomList(Node head) {
if (head == null) {
return null;
}
//步骤一
for (Node node = head; node != null; node = node.next.next) {
Node nodeNew = new Node(node.val);
nodeNew.next = node.next;
node.next = nodeNew;
}
//步骤二
for (Node node = head; node != null; node = node.next.next) {
Node nodeNew = node.next;
nodeNew.random = (node.random != null) ? node.random.next : null;
}
//步骤三
Node headNew = head.next;
for (Node node = head; node != null; node = node.next) {
Node nodeNew = node.next;
node.next = node.next.next;
nodeNew.next = (nodeNew.next != null) ? nodeNew.next.next : null;
}
return headNew;
}
}