剑指 Offer 35. 复杂链表的复制
题目:
请实现 copyRandomList
函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next
指针指向下一个节点,还有一个 random
指针指向链表中的任意节点或者 null
。
示例一:
输入: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例二:
输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例三:
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
解题思路:
①:比较容易想的一种就是使用数据结构HashMap,首先遍历一次链表,创建复制节点到HashMap中,比如A->B->C的链表,先遍历一遍,创建A1,B1,C1,构建A-A1,B-B1,C-C1的映射,然后再遍历一遍,按原链表的节点的next和random指针对复制的元素进行操作。
java实现:
public Node copyRandomList(Node head) {
HashMap<Node,Node> map = new HashMap<>();
Node p = head;
while(p!=null){
Node cp = new Node(p.val);
map.put(p,cp);
p = p.next;
}
p = head;
Node result = map.get(p);
while(p!=null){
result.next = map.get(p.next);
result.random = map.get(p.random);
p = p.next;
result = result.next;
}
return map.get(head);
}
②:也可以不开辟Hash表的空间进行存储实现的方法,每次copy一个新的节点的时候放到被copy的节点后面,这样结构依旧保持,在进行一次遍历设置random指针的时候,只要找当前random指针指向的节点的下一个节点就是复制的节点。具体思路可以看左神LeetCode专题的链表一节。
Java实现:
public Node copyRandomList(Node head){
if(head==null) return null;
Node p = head;
while(p!=null){
Node cp = new Node(p.val); //创建节点
//把复制的节点放到源节点后面
cp.next = p.next;
p.next = cp;
p = p.next.next;
}
p = head;
while(p!=null){
//设置random指针
if(p.random==null) p.next.random = null;
else {
p.next.random = p.random.next;
}
p = p.next.next; //每次跳两个
}
Node p1 = head;
Node p2 = head.next;
Node result = head.next;
while(p1!=null&&p2!=null){ //取出复制的节点,源数据要恢复
p1.next = p2.next;
p1 = p1.next;
if(p1!=null&&p1.next!=null) p2.next = p1.next;
p2 = p2.next;
}
return result;
}