随机算法 & 数据结构
这里要做个取巧的事,考虑到所有value都是 integer,我们可以直接 swap,这样删除 “尾巴” 就是 O(1) 的平均复杂度了。
import java.util.Random;
public class RandomizedSet {
// Key : number
// Value : corresponding index in arraylist
Map<Integer, Integer> map;
List<Integer> list;
Random rd;
/** Initialize your data structure here. */
public RandomizedSet() {
map = new HashMap<Integer, Integer>();
list = new ArrayList<Integer>();
rd = new Random();
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
public boolean insert(int val) {
// Set already has given value
if(map.containsKey(val)) return false;
map.put(val, list.size());
list.add(val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
if(!map.containsKey(val)) return false;
int indexA = map.get(val);
if(indexA != list.size() - 1) swap(list, map, indexA, list.size() - 1);
map.remove(list.get(list.size() - 1));
list.remove(list.size() - 1);
return true;
}
/** Get a random element from the set. */
public int getRandom() {
return list.get(rd.nextInt(list.size()));
}
// a : list index of element a
// b : list index of element b
private void swap(List<Integer> list, Map<Integer, Integer> map, int a, int b){
int valA = list.get(a);
int valB = list.get(b);
int indexA = map.get(valA);
int indexB = map.get(valB);
list.set(a, valB);
list.set(b, valA);
map.put(valA, indexB);
map.put(valB, indexA);
}
}(G) Get random number except blacklist
题目要求:
分析:
因此另一个思考角度是,从 white list 出发。
假如 white list 内存放不下呢?
相当于实现了一个 index -> whitelist[index] 的 mapping,可以保证一次 getRandom() 就可以得到有效元素。
huixuan : 我之前还想过这个问题可以变形成另外一个问题:比如产生长度为k的随机序列,序列中数字的值在[0, n]中sample,但是不可以有重复。要求讨论两个case: k和n差不多大、k远小于n
Random number generator with weight
核心是 cumulative distribution. 计算出 [0.1, 0.3, 0.5, 0.9, 1] 的 cdf 之后,我们可以随机返回一个 【0,1】 之间的数,然后对于 cdf array 做 binary search.
我们要寻找的,就是第一个 random number < cdf[i] 所对应的元素 num[i].
题目描述: Given a data set of unknown size N, uniformly select k elements from the set such that each element has a 1/N probability of being chosen.
分析 & 证明:
O(n) 时间,O(k) 空间。算法和测试代码如下:
代码和流程惊人的简单:
其原理非常类似于一群人在一个黑箱子里抽彩票,for 循环中的每次迭代相当于一个人,每次抽样范围 index = 箱子中剩下的所有彩票,其数量依次递减。到最后每个人虽然抽奖时箱子里彩票总数不同,但是获奖概率却是均等的。
Last updated