-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIDRO1DuplicatesAllowed.java
More file actions
131 lines (114 loc) · 4.37 KB
/
IDRO1DuplicatesAllowed.java
File metadata and controls
131 lines (114 loc) · 4.37 KB
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
package leetcode;
import java.util.*;
/**
* IDRO1DuplicatesAllowed
* https://leetcode-cn.com/problems/insert-delete-getrandom-o1-duplicates-allowed/
*
* @since 2020-10-31
*/
public class IDRO1DuplicatesAllowed {
public static void main(String[] args) {
RandomizedCollection collection = new RandomizedCollection();
System.out.println(collection.insert(0));
System.out.println(collection.remove(0));
System.out.println(collection.insert(-1));
System.out.println(collection.remove(0));
System.out.println(collection.getRandom());
System.out.println(collection.getRandom());
// System.out.println(collection.insert(1));
// System.out.println(collection.remove(1));
// System.out.println(collection.insert(1));
// System.out.println(collection.remove(1));
// System.out.println(collection.getRandom());
// System.out.println(collection.getRandom());
// // 向集合中插入 1 。返回 true 表示集合不包含 1 。
// System.out.println(collection.insert(1));
//
// // 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
// System.out.println(collection.insert(1));
//
// // 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
// System.out.println(collection.insert(2));
//
// // getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
// System.out.println(collection.getRandom());
//
// // 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
// System.out.println(collection.remove(1));
//
// // getRandom 应有相同概率返回 1 和 2 。
// System.out.println(collection.getRandom());
}
static class RandomizedCollection {
Map<Integer, Set<Integer>> container;
List<Integer> values;
/**
* Initialize your data structure here.
*/
public RandomizedCollection() {
this.container = new HashMap<>();
this.values = new ArrayList<>(); // use array instead of linked list
}
/**
* Inserts a value to the collection. Returns true if the collection did not already contain the specified element.
*/
public boolean insert(int val) {
values.add(val);
int index = values.size() - 1;
if (container.containsKey(val)) {
container.get(val).add(index);
return false;
}
Set<Integer> idxs = new HashSet<>();
idxs.add(index);
container.put(val, idxs);
return true;
}
/**
* Removes a value from the collection. Returns true if the collection contained the specified element.
*/
public boolean remove(int val) {
if (values.isEmpty() ||
container.isEmpty() ||
!container.containsKey(val)) {
return false;
}
// KEY: remove from last to begin, don't change other value order
int lastIdx = values.size() - 1;
int lastVal = values.get(lastIdx);
if (lastVal == val) {
// remove idx directly
container.get(lastVal).remove(lastIdx);
} else {
// pick exist index
Set<Integer> idxs = container.get(val);
int targetIdx = 0;
for (Integer idx : idxs) {
targetIdx = idx;
break;
}
// swap idx between val and lastValue
container.get(val).remove(targetIdx);
container.get(lastVal).remove(lastIdx);
container.get(lastVal).add(targetIdx);
values.set(targetIdx, lastVal);
}
values.remove(lastIdx);
// KEY: remove empty values immediately
if (container.get(val).isEmpty()) {
container.remove(val);
}
return true;
}
/**
* Get a random element from the collection.
*/
public int getRandom() {
if (values.isEmpty()) { // bug1
return -1;
}
int idx = (int) Math.floor(Math.random() * values.size());
return values.get(idx);
}
}
}