Java:生成一个恰好为“x”为真的随机布尔数组 - 算法

Posted

技术标签:

【中文标题】Java:生成一个恰好为“x”为真的随机布尔数组 - 算法【英文标题】:Java: Generate a random boolean array with exactly 'x' true - Algorithm 【发布时间】:2014-06-18 21:47:48 【问题描述】:

我正在尝试创建一个算法,该算法可以生成一个带有随机布尔值的布尔数组,假设恰好“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++;                      
                
                
            

    

【问题讨论】:

【参考方案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),只需

    Boolean.TRUE 填充第一个n,其余的用 Boolean.FALSECollections.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);

【讨论】:

您能否提供一些示例代码?谢谢! 然后按照打开哈希表的方式进行操作。只是我讨厌创建太多对象:)

以上是关于Java:生成一个恰好为“x”为真的随机布尔数组 - 算法的主要内容,如果未能解决你的问题,请参考以下文章

检查布尔数组中的所有值是不是为真的最优雅方法是啥?

生成包含随机布尔值的大型 numpy 数组的内存有效方法

查找值为真的布尔数组的索引

生成随机布尔值的最快方法

根据某些标准生成部分随机布尔值数组[关闭]

生成随机布尔概率