题目地址
https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/
题目描述
请实现 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 。
思路
- 遍历链表,复制节点,用Map存起来,遍历完这个时候已有了所有的节点,只需在遍历一次链表,将复制的节点的next和random连接起来即可。
- 既然我们可以将创建后的节点放在map里,那也可以挂在原链表原节点的后面,类似1,复制节点挂在原节点后面,然后去除原节点,连接新节点的random即可。
题解
/**
* @Author: vividzcs
* @Date: 2021/3/4 11:36 下午
*/
public class CopyRandomList {
public static void main(String[] args) throws Exception {
int[][] arr = {{3,-1},{3,0},{3,-1}};
Node head = Node.create(arr);
Node newHead = copyRandomList(head);
Node.check(head, newHead);
head = Node.create(arr);
newHead = copyRandomListV2(head);
Node.check(head, newHead);
}
/**
* 执行用时: 0 ms , 在所有 Java 提交中击败了 100.00% 的用户
* 内存消耗: 37.6 MB , 在所有 Java 提交中击败了 97.89% 的用户
*/
private static Node copyRandomListV2(Node head) {
if (head == null) {
return null;
}
Node current = head;
while (current != null) {
Node next = current.next;
current.next = new Node(current.val);
current.next.next = next;
current = next;
}
current = head;
while (current != null) {
if (current.random != null) {
current.next.random = current.random.next;
}
current = current.next.next;
}
Node newHead = head.next;
current = head;
Node pre = null;
while (current != null) {
pre = current.next;
Node nextCurrent = pre.next;
if (nextCurrent != null) {
pre.next = nextCurrent.next;
}
current.next = nextCurrent;
current = nextCurrent;
}
return newHead;
}
/**
* 执行用时: 0 ms , 在所有 Java 提交中击败了 100.00% 的用户
* 内存消耗: 38.5 MB , 在所有 Java 提交中击败了 13.82% 的用户
*/
public static Node copyRandomList(Node head) {
Node current = head;
Map<Node, Node> map = new HashMap<>();
while (current != null) {
map.put(current, new Node(current.val));
current = current.next;
}
current = head;
while (current != null) {
Node node = map.get(current);
node.next = map.get(current.next);
node.random = map.get(current.random);
current = current.next;
}
return map.get(head);
}
static class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
public static Node create(int[][] arr) {
Map<Integer, Node> map = new HashMap<>();
Node head = new Node(-1);
Node tmp = head;
for (int i=0; i<arr.length; i++) {
Node current = new Node(arr[i][0]);
tmp.next = current;
tmp = current;
map.put(i, tmp);
}
tmp = head.next;
for (int i=0; i<arr.length; i++) {
tmp.random = map.get(arr[i][1]);
tmp = tmp.next;
}
return head.next;
}
/**
* 部分验证, 原节点被修改没检查
* @param old
* @param young
*/
public static void check(Node old, Node young) throws Exception {
Set<Node> set = new HashSet<>();
Node node = old;
while (node != null) {
set.add(node);
node = node.next;
}
node = young;
Map<Node, Integer> map = new HashMap<>();
int index = 0;
while (node != null) {
map.put(node, index++);
node = node.next;
}
node = young;
StringBuilder sb = new StringBuilder("[[");
while (node != null) {
if (set.contains(node) || set.contains(node.random)) {
throw new Exception("program was error!");
}
sb.append(node.val);
sb.append(",");
sb.append(map.get(node.random) == null ? "-1" : map.get(node.random));
sb.append("],[");
node = node.next;
}
sb.replace(sb.length()-2, sb.length(), "]");
System.out.println(sb);
}
}
}