文档阅读
结合哈希表和数组
,使得数组的删除操作时间复杂度变成 O(1)
对数组尾部进行插入和删除操作不会涉及数据搬移,时间复杂度是 O(1)。
在 O(1) 的时间删除数组中的某一个元素 val,可以先把这个元素交换到数组的尾部,然后再 pop 掉。
想高效地,等概率地随机获取元素,就要使用数组作为底层容器
题目
380. O(1) 时间插入、删除和获取随机元素
class RandomizedSet {
List<Integer> list;
Map<Integer, Integer> map;
public RandomizedSet() {
list = new ArrayList<>();
map = new HashMap<>();
}
public boolean insert(int val) {
if(map.containsKey(val)) return false;
map.put(val, list.size());
list.add(val);
return true;
}
public boolean remove(int val) {
if(!map.containsKey(val)) return false;
Integer removeIdx = map.get(val);
map.put(list.get(list.size() - 1), removeIdx);
//数组交换位置
Collections.swap(list, removeIdx, list.size() - 1);
map.remove(val);
list.remove(list.size() - 1);
return true;
}
public int getRandom() {
return list.get((int)(Math.random() * list.size()));
}
}
/**
* 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();
*/
710. 黑名单中的随机数
class Solution {
int size;
Map<Integer, Integer> map;
Random random;
public Solution(int n, int[] blacklist) {
size = n - blacklist.length;
map = new HashMap<>();
random = new Random();
for(int b : blacklist){
map.put(b, 0);//这里放什么值都无所谓只是让map记录这里是黑名单
}
int idx = n - 1;//将所有黑名单都映射到[size, n)之间
for(int b : blacklist){
if(b >= size) continue;//已经在的就不处理
while(map.containsKey(idx)) idx--;
map.put(b, idx);
idx--;
}
}
public int pick() {
int num = random.nextInt(size);
return map.getOrDefault(num, num);//没有命中黑名单就直接走default,命中黑名单就走map
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(n, blacklist);
* int param_1 = obj.pick();
*/