710. 黑名单中的随机数
给定一个包含 [0,n ) 中独特的整数的黑名单 B,写一个函数从 [ 0,n ) 中返回一个不在 B 中的随机整数。

对它进行优化使其尽量少调用系统方法 Math.random() 。

提示:

1 <= N <= 1000000000
0 <= B.length < min(100000, N)
[0, N) 不包含 N,详细参见 interval notation 。
示例 1:

输入:
["Solution","pick","pick","pick"]
[[1,[]],[],[],[]]
输出: [null,0,0,0]
示例 2:

输入:
["Solution","pick","pick","pick"]
[[2,[]],[],[],[]]
输出: [null,1,1,1]
示例 3:

输入:
["Solution","pick","pick","pick"]
[[3,[1]],[],[],[]]
Output: [null,0,0,2]
示例 4:

输入:
["Solution","pick","pick","pick"]
[[4,[2]],[],[],[]]
输出: [null,1,3,1]

解题思路
利用逻辑上的紧凑数组实现
N个数中,加入有m个黑名单。则将非黑名单的数字逻辑上存放在前N-m中。这样可以通过随机索引保证随机
如果黑名单在前半部分,则与后半部分的值交换---此时用map存index到val的映射。其他正常的index=val。则不用再次存储
ps:代码看了好几遍没问题,但是运行不过
试运行结果正确,提交时又不通过。同样的用例。之后再看
java代码

class Solution {
    public static int sz;
    public static Map<Integer,Integer> map=new HashMap<>();

    public Solution(int N, int[] blacklist) {
        for(int b:blacklist){
            map.put(b,-1);
        }
        sz=N-blacklist.length;
        int last=N-1;
        for(int b:blacklist){
            if(b>=sz){
                continue;
            }
            //找到未在前方的最后一个正常数
            while(map.containsKey(last)){
                last--;
            }
            //交换
            map.put(b,last);
            //舍弃交换后的黑名单
            last--;
        }
    }

    public int pick() {
        int index=(int)(Math.random()*sz);
        //交换过的数在map中,其他的就等于index
        if(map.containsKey(index)){
            return map.get(index);
        }
        return index;
    }
}

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(N, blacklist);
 * int param_1 = obj.pick();
 */