概述
请设计一个算法,对于给定整数N 和 黑名单blacklist;使得随机返回[0, N-1] 范围的整数;要求返回概率相同,并且不包含黑名单blacklist中的整数。
代码模板
import java.util.*;
class Solution {
public Solution(int n, int[] blacklist) {
}
public int pick() {
}
public static void main(String[] args) {
Solution solution = new Solution(10, new int[]{6, 3, 9});
System.out.println(solution.pick());
}
}
示例1
示例 1:
输入
["Solution", "pick", "pick", "pick", "pick", "pick", "pick", "pick"]
[[10, [6, 3, 9]], [], [], [], [], [], [], []]
输出
[null, 8, 4, 1, 7, 1, 0, 4]
解题思路
第一种解法:
1.直接记录n和blacklist,并且将blacklist写入到HashSet中。
2.直接调用int v=Random.next(n),考虑以下情况:
- case1,如果v在HashSet中,则重新调用 v=Random.next(n),直到v不在HashSet中。
- case2,如果v不在HashSet中,则直接返回v。
第一种解法,能实现所有的要求,但是在重复度非常高的情况下,耗时会非常高,所以给出第二种解法。
第二种解法:
1.记录n和blacklist,并且将blacklist写入到HashSet中,
- 准备一个int bound=n-blacklist.length; 实际需要随机的种子;
- 准备一个map,记录blacklist中的数字和没有在[0, bound-1]出现的数字;
2.直接调用int v=Random.next(bound),考虑以下情况:
- case1,如果v在HashSet中,则返回map.get(v);
- case2,如果v不在HashSet中,则直接返回v。
代码实现
第一种解法代码实现:
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
class Solution {
private int bound;
private Random random;
private Set<Integer> set;
public Solution1(int n, int[] blacklist) {
this.bound = n;
this.set = new HashSet<>();
this.random = new Random();
for (int black : blacklist) {
set.add(black);
}
}
public int pick() {
int v = random.nextInt(bound);
// 如果在blacklist中,则循环遍历,直到结束
while (set.contains(v)) {
v = random.nextInt(bound);
}
return v;
}
}
第二种解法代码实现:
import java.util.*;
class Solution {
private int bound;
private Random random;
private Set<Integer> set;
private Map<Integer, Integer> map;
public Solution(int n, int[] blacklist) {
int length = blacklist.length;
this.bound = n - length;
this.map = new HashMap<>();
this.set = new HashSet<>();
this.random = new Random();
for (int black : blacklist) {
set.add(black);
}
int b = bound;
for (int i = 0; i < length; i++) {
// 如果blacklist[i]比bound小,则需要加入到map中;
if (blacklist[i] < bound) {
// 加入map的数据也不能在blacklist
while (set.contains(b)) {
b++;
}
map.put(blacklist[i], b);
b++;
}
}
}
public int pick() {
int v = random.nextInt(bound);
// 如果在blacklist中,则返回map中的数字
if (set.contains(v)) {
return map.get(v);
}
return v;
}
public static void main(String[] args) {
Solution solution = new Solution(10, new int[]{6, 3, 9});
System.out.println(solution.pick());
}
}