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.FALSE
做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);
【讨论】:
您能否提供一些示例代码?谢谢! 然后按照打开哈希表的方式进行操作。只是我讨厌创建太多对象:)以上是关于Java:生成一个恰好为“x”为真的随机布尔数组 - 算法的主要内容,如果未能解决你的问题,请参考以下文章