剑指 Offer 35. 复杂链表的复制
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:
输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:
输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
提示:
-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。
解题思路
该题具有两种解题思路 解题的核心是 记录好 旧节点与新节点之间的对应关系:
-
使用 哈希表映射 来存储 Node
对于源链表中的每一个节点node和其复制节点newNode,都有唯一键值对<node,newNode>
对于newNode , newNode.next = map.get(node.next);
newNode.random = map.get(current.random);
-
拼接 + 拆分 链表来记录Node
源链表 node1 -> node2 -> node3 -> node4 …
新链表 newNode1 -> newNode2 -> newNode3 -> newNode4 …
拼接为链表:
node1 -> newNode1 -> node2 -> newNode2 …
通过以上链表可以解决random指针问题
newNode.random = node1.random.next;
拆分该链表:
node.next = node.next.next;
newNode = newNode.next.next;
代码示例
- Map方法
/*
// 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>{
Map<Node,Node> map = new HashMap<Node,Node>();
Node current = head;
while(current!=null){
Node node = new Node(current.val);
map.put(current,node);
current = current.next;
}
current = head;
while(current!=null)
{
Node newNode = map.get(current);
newNode.next = map.get(current.next);
newNode.next = map.get(current.random);
current = current.next;
}
return map.get(head);
}
}
2.拼接 + 拆分 链表
public Node copyRandomList(Node head){
if(head==null)
{
return head;
}
//复制每一个节点,并将新节点放在旧节点的后面
/*
newcurrent.next = current.next;
current.next = newcurrent;
*/
Node newHead = new Node(0);
Node current = head;
Node newcurrent = headHead;
while(current!=null)
{
newcurrent = new Node(current.val);
newcurrent.next = current.next;
current.next = newcurrent;
current = current.next.next;
}
//在上面已经形成了一个以head为头的复制组合链表
// a -> a' -> b -> b' ....
//接下来 把每一个新节点的 random指针补全
current = head;
while(current!=null)
{
if(current.random == null)
{
current.next.random = null;
}else{
current.next.random = current.random.next;
}
current = current.next;
}
//接下来把原链表和新链表拆开
current = head;
newHead = current.next;
newcurrent = newHead;
while(current!=null)
{
if(newcurrent.next==null){
current.next = null;
break;
}
current.next = current.next.next;
newcurrent.next = newcurrent.next.next;
current = current.next;
newcurrent = newcurrent.next;
}
return newHead;
}