1. 分析
我们都知道在Java
的HashMap
中插入和删除的时间复杂度为O(1)
,故而我们可以考虑使用HashMap
来作为底层的数据存储,但是因为HashMap
中没有索引,所以在随机获取一个元素的时候做不到时间复杂度为O(1)
,所以需要引入额外的数据结构ArrayList
。
在随机获取一个元素的时候,我们就在ArrayList
中随机生成一个下标,然后返回其值即可。
在添加和删除的时候,使用HashMap
来完成。
这里需要解决的主要问题就是如何将两者进行关联起来。比如:在删除元素的时候,应该不仅是在HashMap
中删除,而且需要对应的删除ArrayList
中的值,而如果没有特殊的关联,那么在ArrayList
中进行删除元素的查找就是O(n)
的时间复杂度了,显然不满足需求。
2. 解决
在HashMap
中存储<key, value>
,那么key
可以存储为当前的值,而value
为当前值在ArrayList
的下标。
在ArrayList
中存储的元素是具体的值。
通过上面的映射,可以做到添加和删除的时候及时更新ArrayList
的值,然后可以做到随机获取一个元素。
在添加和删除的时候,需要更新这两部分即可。操作规则为:
- 插入一个数时,直接放到
ArrayList
最后; - 删除一个数时,让
ArrayList
最后一个数字去替换当前待删除元素;
class RandomizedSet {
private HashMap<Integer, Integer> map;
private ArrayList<Integer> list;
private Random random;
public RandomizedSet() {
map = new HashMap<>();
list = new ArrayList<>();
random = new Random();
}
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;
int lastEle = list.get(list.size() - 1);
int idx = map.get(val);
list.set(idx, lastEle);
map.put(lastEle, idx);
list.remove(list.size() - 1);
map.remove(val);
return true;
}
public int getRandom() {
int idx = random.nextInt(list.size());
return list.get(idx);
}
}
结果:
题目地址