【问题标题】:Java: Generate a random boolean array with exactly 'x' true - AlgorithmJava:生成一个恰好为“x”为真的随机布尔数组 - 算法
【发布时间】:2023-03-29 13:30:02
【问题描述】:

我正在尝试创建一个算法,该算法可以生成一个带有随机布尔值的布尔数组,假设恰好“x”个布尔值是真实的。我已经解决了算法,但很好奇是否有更清洁的方法。

以下是我的工作示例。两个变量songToPlay 和songsToDownload 是随机生成的变量,但在这种情况下,我将它们分别设置为固定数字8 和4。另一个需要提的重点是数组中的第一个布尔值必须为真。

问题:我需要随机生成一个由 8 个真假值组成的数组,正好是 4 个 的值是真实的。

Random ran = new Random();
    int songsToPlay = 8;
    int songsToDl = 4
    Boolean[] ranDownloads = new Boolean[songsToPlay];
    ranDownloads[0] = true;
    int counter = 1; //track how many are true, given the first one is always true.

    for(int i = 1; i < ranDownloads.length; i++) {
            if((songsToDl - counter) >= (ranDownloads.length - i)) {
                ranDownloads[i] = true;
                counter++;
            } else {
                if(counter == songsToDl) {
                    while (i < ranDownloads.length) {
                        ranDownloads[i++] = false;
                    }
                break;
                } else {
                ranDownloads[i] = ran.nextBoolean();
                if(ranDownloads[i] == true) {
                    counter++;                      
                }
                }
            }

    }

【问题讨论】:

    标签: java arrays algorithm random boolean


    【解决方案1】:

    我需要随机生成一个包含 8 个真假值的数组,其中正好 4 个值为真。

    这是洗牌问题的一种变体

    List<Boolean> flags = new ArrayList<Boolean>();
    for(int i = 0; i < 4; i++) flags.add(true);
    for(int i = 0; i < 4; i++) flags.add(false);
    Collections.shuffle(flags);
    

    这在 O(N) 时间内完成,您可以确定您拥有所需的真/假数。

    注意:所有解决方案发生的机会均等。仅更改值直到获得所需总数的问题在于,很难确保生成的结果没有偏差。

    来自Collections.shuffle(List)的JavaDoc

    使用默认随机源随机排列指定列表。所有排列发生的可能性大致相等。

    此实现从最后一个元素到第二个元素向后遍历列表,反复将随机选择的元素交换到“当前位置”。元素是从列表中从第一个元素到当前位置(含)的部分中随机选择的。

    此方法以线性时间运行。 如果指定列表没有实现 RandomAccess 接口且很大,则此实现在打乱之前将指定列表转储到数组中,并将打乱后的数组转储回进入列表。这避免了由于将“顺序访问”列表改组而导致的二次行为。

    【讨论】:

    • @JensG 是的,我已经添加了参考。
    • 哇,和我写的有什么不同!清楚地表明我在 Java 方面仍然比较精干。非常感谢。可以接受两个答案吗?有人发布了类似的内容,但您的内容更详细。
    • @user3501875 如果您无法在答案之间进行选择,请将代表分配给代表最少的那个。 ;)
    • @user3501875:您仍然可以投票给其他答案。
    • 谢谢,不幸的是,直到我自己有 15 个才能代表。我会接受这个以获取更多信息!
    【解决方案2】:

    随机选择四个数组索引并将它们的内容设置为 true(并确保您不会两次使用相同的索引)。

    【讨论】:

      【解决方案3】:

      鉴于您使用的是 Object 数组(Boolean 而不是 boolean),只需

      1. Boolean.TRUE 填充第一个n,其余的用 Boolean.FALSE
      2. Collections.shuffle(Arrays.asList(yourArray))

      一切准备就绪。

      见:Collections.shuffle(list)Arrays.asList(array)

      【讨论】:

      • 伟大的思想......我同意(因为我的回答相同,甚至在假之前添加了真)但我认为在这里使用列表比使用数组更容易。
      • @PeterLawrey 我同意,但我想更接近 OPs 版本
      • 我是这么认为的,+1 您的方法的优势,因为这涉及最少的更改。
      【解决方案4】:

      为什么不创建一个 BitSet 并将 x 位随机翻转为 1。

      根据要求提供示例代码:

      BitSet bs = new BitSet(songCount);
      
      Random random = new Random();
      // x: target number of true values
      for (int i = 0; bs.cardinality() < x; i++) {
          bs.set(random.nextInt() % songCount);
      }
      

      【讨论】:

      • 您能否提供一些示例代码?谢谢!
      • 然后按照打开哈希表的方式进行操作。只是我讨厌创建太多对象:)
      猜你喜欢
      • 2011-11-02
      • 2014-05-30
      • 2014-08-04
      • 2011-02-08
      • 1970-01-01
      • 2017-09-05
      • 1970-01-01
      • 2017-10-30
      相关资源
      最近更新 更多