์ฒซ๋ฒ์งธ๋ก ๋๋ ์๊ฐ์ ์ผ๋จ ํ ์ธ์ด์ ๋ง์ API๋ค์ ๊ณต๋ถํด์ผ๊ฒ ๋ค์ด๋ค.
java.util.Random
Random random = new Random()
random.nextInt(max - min) + min;
java.util.HashSet
HashSet<String> names = new HashSet<>();
.add, .remove, .contains, .size
runs in O(1) time. java.util.ArrayList
.add(E) O(1), .add(index, e) O(n), .get(index) O(1), .set(index) O(1), .remove(index) O(n), .size() O(1), .isEmpty() O(1), .contains() O(n)
java.util.HashMap
.put(k,v) O(1), .get(key) O(1), .remove() -> removed element O(1), .containsKey() O(1), .containsValue() O(n), .size()
insert์ remove๋ ๊ทธ๋ฅ ์๋ HashSet API๋๋ก ์ฌ์ฉํ๋ฉด ๋ ๊ฒ์ด๋ค.
getRandom()
์ ๋ ๋ค๋ฅธ ๋ฐฐ์ด์ ๋ง๋ค์ด add()
์ remove()
๋ฅผ ํ๋ ๋์ element๋ค์ ํ๋์ฉ ์ถ๊ฐํ๊ณ nextInt(size)๋ฅผ random index๋ก ํ์ฌ ๊ทธ element๋ฅผ ๋ฐํํ๋ฉด ๋ ๋ฏ ํ๋ค.
-> ํ์ง๋ง remove() ๋ O(n)์ด์ด์ ์ด ๋ฐฉ๋ฒ์ ์๋๋ค.
๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก HashMap<Integer, Integer>์ ์ฌ์ฉํด key์๋ RandomSet์ element๋ฅผ ์ ์ฅํ๊ณ value์๋ random access์ ์ฌ์ฉ๋ ArrayList์ element๋ค์ index๋ฅผ ์ ์ฅํ๋ค. ๊ทธ๋ฆฌ๊ณ swap and pop๋ฅผ ์ฌ์ฉํด ๊ทธ index์ ์๋ element์ ๋ง์ง๋ง index์ ์๋ element์ ๋ง ๋ฐ๊พธ๊ณ popํด์ฃผ๋ฉด O(1)์ด๋ค. ์ด๋ฌ๋ฉด HashMap์ ์๋ ์ ์ ๋งจ ๋ค์ ์๋ ๊ทธ element์ index๋ ๋ฐ๊ฟ์ฃผ์ด์ผ ํ๋ค.
์ด๋ ๊ฒ ํ๋ค๋ฉด .add(), .remove()
๋ O(1), getRandom()
๋ O(1)์ด๋ค.
import java.util.Random;
import java.util.HashMap;
class RandomizedSet {
private HashMap<Integer, Integer> hm;
private ArrayList<Integer> al;
private Random random = new Random();
public RandomizedSet() {
this.hm = new HashMap<>();
this.al = new ArrayList<>();
}
public boolean insert(int val) {
if (!this.hm.containsKey(val)) {
this.al.add(val);
int index = this.al.size();
this.hm.put(val, index);
}
return false;
}
public boolean remove(int val) {
if (this.hm.containsKey(val)) {
// first, remove the element in the hashmap and get the index.
int index = this.hm.remove(val);
// second, swap and pop the element with the last element in the arraylist.
int temp = this.al.get(this.al.size() - 1);
this.al.set(this.al.size() - 1, val);
this.al.set(index, temp);
this.al.remove(this.al.size() - 1);
// third, update the index of the swapped element .
this.hm.put(temp, index);
return true;
}
return false;
}
public int getRandom() {
int size = this.al.size();
int randomIndex = random.nextInt(size);
return this.al.get(randomIndex);
}
}
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet obj = new RandomizedSet();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/
๋ณ๋ก ์๊ฐ์ ๊น๊ฒ ์ ํ ๋ต์ธ ๊ฒ ๊ฐ๋ค. remove() ๋ก์ง์ด ์ด์ํ๋ค.
import java.util.Random;
import java.util.HashMap;
class RandomizedSet {
private HashMap<Integer, Integer> hm;
private ArrayList<Integer> al;
private Random random = new Random();
public RandomizedSet() {
this.hm = new HashMap<>(); // <element, indexInArraylist>
this.al = new ArrayList<>();
}
public boolean insert(int val) {
if (!this.hm.containsKey(val)) {
this.al.add(val);
this.hm.put(val, this.al.size() - 1);
return true;
}
return false;
}
public boolean remove(int val) {
if (this.hm.containsKey(val)) { // if the element exists in the hashset,
// first, remove the element in the hashmap and get the index.
int index = this.hm.remove(val);
// second, swap and pop the element with the last element in the arraylist.
int toUpdate = this.al.get(this.al.size() - 1);
// 1. set the index with the last element
this.al.set(index, toUpdate);
// 2. update the index of the last element in the hash map
this.hm.put(toUpdate, index);
// 3. remove the last element
this.al.remove(this.al.size() - 1);
return true;
}
return false;
}
public int getRandom() {
int size = this.al.size();
int randomIndex = random.nextInt(size);
return this.al.get(randomIndex);
}
}
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet obj = new RandomizedSet();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/
๊ฑฐ์ ๋ค ํ๋ค. ํ์ง๋ง test case ๋ช๊ฐ๊ฐ ํต๊ณผ๊ฐ ์ ๋๋ค.
input:
["RandomizedSet","remove","remove","insert","getRandom","remove","insert"]
[[],[0],[0],[0],[],[0],[0]]
output:
[null,false,false,true,0,true,false]
expected:
[null,false,false,true,0,true,true]
์ด์ ๋ฅผ ๋ณด๋ ๋ง์ฝ this.hm.remove(val)
๋ฅผ ํตํด ์ป์ this.al์์์ ๊ฐ์ ์ซ์์ ์ธ๋ฑ์ค๊ฐ ArrayList์ ๋์ ์๋ค๋ฉด, ๊ทธ๋ ๋ค๋ฉด ๊ทธ ์ซ์์ ๋ํ ์ธ๋ฑ์ค ๊ฐ์ ๋ค์ ์
๋ฐ์ดํธ๋ฅผ ํด์ค ํ์๊ฐ ์์๋ค๋ ๊ฒ์ด๋ค. ๋ง์ฝ ์
๋ฐ์ดํธ๋ฅผ ํ๋ค๋ฉด ๊ทธ ์ซ์๋ ๋ค์ HashMap์ ๋ค์ด๊ฐ๊ฒ ๋ ๊ฒ์ด๋ค.
import java.util.Random;
import java.util.HashMap;
class RandomizedSet {
private HashMap<Integer, Integer> hm;
private ArrayList<Integer> al;
private Random random = new Random();
public RandomizedSet() {
this.hm = new HashMap<>(); // <element, indexInArraylist>
this.al = new ArrayList<>();
}
public boolean insert(int val) {
if (!this.hm.containsKey(val)) {
this.al.add(val);
this.hm.put(val, this.al.size() - 1);
return true;
}
return false;
}
public boolean remove(int val) {
if (this.hm.containsKey(val)) { // if the element exists in the hashset,
// first, remove the element in the hashmap and get the index.
int index = this.hm.remove(val);
// second, swap and pop the element with the last element in the arraylist.
int toUpdate = this.al.get(this.al.size() - 1);
// 1. set the index with the last element
this.al.set(index, toUpdate);
// 2. update the index of the last element in the hash map
if (index != this.al.size() - 1)
this.hm.put(toUpdate, index);
// 3. remove the last element
this.al.remove(this.al.size() - 1);
return true;
}
return false;
}
public int getRandom() {
int size = this.al.size();
int randomIndex = random.nextInt(size);
return this.al.get(randomIndex);
}
}
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet obj = new RandomizedSet();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/