【数组】黑名单中的随机数

概述

请设计一个算法,对于给定整数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());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值