-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNo138CopyListWithRandomPointer.java
157 lines (136 loc) · 3.86 KB
/
No138CopyListWithRandomPointer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package com.wzx.leetcode;
import java.util.*;
import java.util.stream.Collectors;
/**
* @see <a href="https://leetcode.com/problems/copy-list-with-random-pointer/">https://leetcode.com/problems/copy-list-with-random-pointer/</a>
* @author wzx
*/
public class No138CopyListWithRandomPointer {
/**
* 将带随机指针的链表看成图(每个结点通过next和random和其他节点连接),使用带备忘录的深搜
* <p>
* time: O(n)
* space: O(n)
*/
public Node copyRandomList1(Node head) {
return recursion(head, new HashMap<>());
}
private Node recursion(Node node, Map<Node, Node> memo){
if(node == null) return null;
if(memo.containsKey(node)) return memo.get(node);
Node newNode = new Node(node.val);
memo.put(node, newNode);
newNode.next = recursion(node.next, memo);
newNode.random = recursion(node.random, memo);
return newNode;
}
/**
* 按照next顺序遍历链表,保存已经clone过的节点
* <p>
* time: O(n)
* space: O(n)
*/
public Node copyRandomList2(Node head) {
if (head == null) return null;
Map<Node, Node> visit = new HashMap<>();
Node newHead = new Node(head.val);
visit.put(head, newHead);
Node node = head;
Node newNode = newHead;
while (node != null) {
newNode.random = cloneNode(node.random, visit);
newNode.next = cloneNode(node.next, visit);
newNode = newNode.next;
node = node.next;
}
return newHead;
}
private Node cloneNode(Node node, Map<Node, Node> visit) {
if (node == null) return null;
if (visit.containsKey(node)) return visit.get(node);
Node newNode = new Node(node.val);
visit.put(node, newNode);
return newNode;
}
/**
* 将clone后的节点放在当前节点后面,newNode.random = node.random.next
* <p>
* time: O(n)
* space: O(1)
*/
public Node copyRandomList3(Node head) {
if (head == null) return null;
// 复制结点
Node node = head;
while(node != null){
Node newNode = new Node(node.val);
// clone结点接到原结点后面
Node nextNode = node.next;
node.next = newNode;
newNode.next = nextNode;
// 遍历
node = nextNode;
}
// 复制random
node = head;
while(node != null){
Node newNode = node.next;
Node randomNode = node.random;
if(randomNode != null) newNode.random = randomNode.next;
node = node.next.next;
}
// 分开两个链表
node = head;
Node newHead = node.next;
while(node != null){
Node newNode = node.next;
node.next = node.next.next;
if(newNode.next != null) newNode.next = newNode.next.next;
node = node.next;
}
return newHead;
}
public static class Node {
public int val;
public Node next;
public Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
public static Node build(List<List<Integer>> data) {
Node pre = new Node(0);
List<Node> nodes = new ArrayList<>(data.size());
for (List<Integer> pointer : data) {
int num = pointer.get(0);
Node node = new Node(num);
nodes.add(node);
pre.next = node;
pre = node;
}
for (int i = 0; i < data.size(); i++) {
Integer next = data.get(i).get(1);
if (next != null) {
nodes.get(i).random = nodes.get(next);
}
}
return nodes.get(0);
}
public List<List<Integer>> toArray() {
List<Node> nodes = new ArrayList<>();
Node node = this;
while (node != null) {
nodes.add(node);
node = node.next;
}
return nodes.stream().map(x -> {
Integer index = nodes.indexOf(x.random);
if (index == -1) {
index = null;
}
return Arrays.asList(x.val, index);
}).collect(Collectors.toList());
}
}
}