Skip to content

Commit 0385511

Browse files
committed
Implement insert-delete-getrandom-o1-duplicates-allowed
name: insert-delete-getrandom-o1-duplicates-allowed url: https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed difficulty: 3 time: 40 ms time-rank: 96.84 % time-complexity: O(1) space: 26.7 MB space-rank: 56.46 % space-complexity: O(N) Fixes #46 Signed-off-by: Christopher Friedt <[email protected]>
1 parent 7d1f116 commit 0385511

2 files changed

+171
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2021, Christopher Friedt
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
#include <gtest/gtest.h>
8+
9+
#include "insert-delete-getrandom-o1-duplicates-allowed.cpp"
10+
11+
using namespace std;
12+
13+
TEST(InsertDeleteGetrandomO1DuplicatesAllowed, example1) {
14+
RandomizedCollection c;
15+
16+
EXPECT_EQ(true, c.insert(1));
17+
EXPECT_EQ(false, c.insert(1));
18+
EXPECT_EQ(true, c.insert(2));
19+
20+
int n1s = 0;
21+
int n2s = 0;
22+
for (int i = 0; i < 1000; ++i) {
23+
if (1 == c.getRandom()) {
24+
++n1s;
25+
continue;
26+
}
27+
if (2 == c.getRandom()) {
28+
++n2s;
29+
continue;
30+
}
31+
}
32+
33+
// around 66%
34+
EXPECT_GE(n1s, 600);
35+
36+
EXPECT_EQ(true, c.remove(1));
37+
38+
n1s = 0;
39+
n2s = 0;
40+
for (int i = 0; i < 1000; ++i) {
41+
if (1 == c.getRandom()) {
42+
++n1s;
43+
continue;
44+
}
45+
if (2 == c.getRandom()) {
46+
++n2s;
47+
continue;
48+
}
49+
}
50+
51+
// around 50%
52+
EXPECT_GE(n1s, 475);
53+
}
54+
55+
TEST(InsertDeleteGetrandomO1DuplicatesAllowed, example2) {
56+
RandomizedCollection c;
57+
EXPECT_EQ(true, c.insert(0));
58+
EXPECT_EQ(true, c.remove(0));
59+
EXPECT_EQ(true, c.insert(-1));
60+
EXPECT_EQ(false, c.remove(0));
61+
62+
for (int i = 0; i < 10; ++i) {
63+
EXPECT_EQ(-1, c.getRandom());
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2021, Christopher Friedt
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
// clang-format off
8+
// name: insert-delete-getrandom-o1-duplicates-allowed
9+
// url: https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed
10+
// difficulty: 3
11+
// clang-format on
12+
13+
#include <unordered_map>
14+
#include <unordered_set>
15+
#include <vector>
16+
17+
using namespace std;
18+
19+
class RandomizedCollection {
20+
public:
21+
RandomizedCollection() {}
22+
23+
/** Inserts a value to the collection. Returns true if the collection did not
24+
* already contain the specified element. */
25+
bool insert(int val) {
26+
27+
auto it = index.find(val);
28+
bool unique;
29+
30+
if (index.end() == it) {
31+
unique = true;
32+
} else {
33+
unique = false;
34+
}
35+
36+
elements.push_back(val);
37+
index[val].insert(elements.size() - 1);
38+
39+
return unique;
40+
}
41+
42+
/** Removes a value from the collection. Returns true if the collection
43+
* contained the specified element. */
44+
bool remove(int val) {
45+
46+
auto it = index.find(val);
47+
if (index.end() == it) {
48+
return false;
49+
}
50+
51+
int val_idx = *(it->second.begin());
52+
53+
// val2 is whatever is at the back / tail of elements
54+
int val2_idx = elements.size() - 1;
55+
int val2 = elements[val2_idx];
56+
57+
if (val2_idx == val_idx) {
58+
// element is already at the back, so just
59+
// pop it out and erase the back index
60+
// O(1)
61+
elements.pop_back();
62+
// O(1)*O(1) = O(1)
63+
index[val].erase(val_idx);
64+
if (index[val].empty()) {
65+
index.erase(val);
66+
}
67+
return true;
68+
}
69+
70+
// swap values at the two indeces
71+
swap(elements[val_idx], elements[val2_idx]);
72+
// get rid of val
73+
elements.pop_back();
74+
index[val].erase(val_idx);
75+
if (index[val].empty()) {
76+
index.erase(val);
77+
}
78+
79+
// update the index of the val2 instance that moved
80+
index[val2].erase(val2_idx);
81+
index[val2].insert(val_idx);
82+
83+
return true;
84+
}
85+
86+
/** Get a random element from the collection. */
87+
int getRandom() {
88+
long pos = ::random() % elements.size();
89+
return elements[pos];
90+
}
91+
92+
protected:
93+
vector<int> elements;
94+
95+
// key is the "value" to be added / removed from the collection
96+
// value is an set of indices where "value" is found in elements
97+
unordered_map<int, unordered_set<int>> index;
98+
};
99+
100+
/**
101+
* Your RandomizedCollection object will be instantiated and called as such:
102+
* RandomizedCollection* obj = new RandomizedCollection();
103+
* bool param_1 = obj->insert(val);
104+
* bool param_2 = obj->remove(val);
105+
* int param_3 = obj->getRandom();
106+
*/

0 commit comments

Comments
 (0)