如何解决;“生日悖论”;在java中不使用嵌套循环?
我曾经尝试过嵌套循环的问题,但是如果不使用嵌套循环并且在同一个类文件中,如何解决它呢。问题是找出两个人在一个群体中拥有相同生日的概率。它应该产生以下输出:在一组5人和10000个模拟中,概率为2.71%。注意:使用arraylist或hashmap是可能的。但我不知道怎么做。多谢各位如何解决;“生日悖论”;在java中不使用嵌套循环?,java,android-studio,Java,Android Studio,我曾经尝试过嵌套循环的问题,但是如果不使用嵌套循环并且在同一个类文件中,如何解决它呢。问题是找出两个人在一个群体中拥有相同生日的概率。它应该产生以下输出:在一组5人和10000个模拟中,概率为2.71%。注意:使用arraylist或hashmap是可能的。但我不知道怎么做。多谢各位 public void process() { int groupSize = System.out.getSize(); int simulationCount = System.out.getC
public void process() {
int groupSize = System.out.getSize();
int simulationCount = System.out.getCount();
if (groupSize < 2 || groupSize > 365) {
System.out.makeAlertToast("Group Size must be in the range 2-365.");
return;
}
if (simulationCount <= 0) {
System.out.makeAlertToast("Simulation Count must be positive.");
return;
}
double percent = calculate(groupSize, simulationCount);
// report results
System.out.println("For a group of " + groupSize + " people, the percentage");
System.out.println("of times that two people share the same birthday is");
System.out.println(String.format("%.2f%% of the time.", percent));
}
public double calculate(int size, int count) {
int numTrialSuccesses = 0;
// Repeat and count.
for (int n=0; n < count; n++) {
Random rand = new Random(n);
// Generate birthdays (random array)
int[] birthdays = new int [size];
for (int i=0; i <size; i++) {
birthdays[i] = rand.nextInt (365);
}
// Check if any two match.
boolean matchExists = false;
for (int i=0; i < size; i++) {
for (int j=0; j < size; j++) {
if ( (i != j) && (birthdays[i] == birthdays[j]) ) {
// Note: musn't forget the i!=j test above!
matchExists = true;
if (matchExists) break;
}
}
}
if (matchExists) {
numTrialSuccesses ++;
}
} //end-for-trials
double prob = ((double) numTrialSuccesses *100)/ (double) count;
return prob ;
}
}
公共作废流程(){
int groupSize=System.out.getSize();
int simulationCount=System.out.getCount();
if(groupSize<2 | | groupSize>365){
System.out.makeAlertToast(“组大小必须在2-365之间”);
返回;
}
如果(模拟计数此代码:
int[] birthdays = new int [size];
for (int i=0; i <size; i++) {
birthdays[i] = rand.nextInt (365);
}
// Check if any two match.
boolean matchExists = false;
for (int i=0; i < size; i++) {
for (int j=0; j < size; j++) {
if ( (i != j) && (birthdays[i] == birthdays[j]) ) {
// Note: musn't forget the i!=j test above!
matchExists = true;
if (matchExists) break;
}
}
}
if (matchExists) {
numTrialSuccesses ++;
}
int[]生日=新int[size];
对于(int i=0;i一种使用奇特数据结构的解决方案HashSet
。如评论中所述,您可以使用365个元素的布尔数组,如果遇到该数组,可以将其切换为true
下面是一个类似的想法。如果集合中还不包含生日,则将每个生日添加到集合中。如果集合中确实包含生日,则增加计数器。现在,您不需要麻烦的第二次迭代,因此您的时间复杂度将降到O(n)。由于集合中的查找具有恒定的时间,因此它将降到O(n)
public double calculate(int size, int count) {
int numTrialSuccesses = 0;
// Repeat and count.
for (int n=0; n < count; n++) {
Random rand = new Random(n);
Set<Integer> set = new HashSet<Integer>();
for (int i=0; i <size; i++) {
int bday = rand.nextInt (365);
Integer bday1 = new Integer(bday);
if(set.contains(bday1)){
numTrialSuccesses++;
break;
}else{
set.add(bday1);
}
}
} //end-for-trials
double prob = ((double) numTrialSuccesses *100)/ (double) count;
//like wise comments have noted this is not the probability!!! Just a simulation
return prob ;
}
public双重计算(整数大小,整数计数){
int numtrialsuccess=0;
//重复数数。
对于(int n=0;n
double calculateProbability(int trials, int people) {
//for trials = 10_000, people = 5
int timesWithSharedBirthday = IntStream.range(0,trials) // Run 10_000 trials
// generate 5 bdays, count distinct ones. Filter out those with 5 distinct
.filter(i -> ThreadLocalRandom.current().ints(people,1,365).distinct().count() != people)
.count(); // Add up the runs without five distinct bdays.
return probability = 100.0 * timesWithSharedBirthday / trials;
}
我不知道你的在线分级机会怎么样,但是用流练习是很有趣的。没有任何必要用固定数量的生日来超越原语
创建一个包含365个存储桶的数组,并在每个存储桶中记下生日的日期。这样可以使用高效的数组操作
下面的代码不是每次都创建一个新数组,而是使用System.arraycopy
在现有数组上复制一个调零后的数组,这样可以获得一些性能
尽管如此,与前面给出的HashSet
示例相比,性能增益充其量是适中的,性能提高了5到6倍,但并没有提高几个数量级。
因此,如果使用HashSet
和类似的工具可以提高清晰度,那么就要提高清晰度
public double calculate(int size, int count) {
int numTrialSuccesses = 0;
int[] daysOfYear = new int[365];
final int[] empty = new int[365];
// Repeat and count.
for (int n = 0; n < count; n++) {
Random rand = new Random(n);
// Efficiently clear out the array
System.arraycopy(empty, 0, daysOfYear, 0, 365);
boolean matchExists = false;
for (int i = 0; i < size; i++) {
int birthday = rand.nextInt(365);
// Compare, then increment, the bucket for the birthday
if(daysOfYear[birthday]++>0){
matchExists = true;
break;
}
}
if (matchExists) {
numTrialSuccesses++;
}
} //end-for-trials
double prob = ((double) numTrialSuccesses * 100) / (double) count;
return prob;
}
public双重计算(整数大小,整数计数){
int numtrialsuccess=0;
int[]daysOfYear=新int[365];
最终整数[]空=新整数[365];
//重复数数。
对于(int n=0;n0天){
matchExists=true;
打破
}
}
如果(匹配存在){
numtrialsuccess++;
}
}//审判结束
双概率=((双)numTrialSuccesses*100)/(双)计数;
返回问题;
}
你遇到了什么问题?你目前的方法是模拟这些概率。你知道你可以简单地计算它们吗?给定一组人的数量,你只需做一些数学运算,就可以得到匹配生日的确切概率。只需使用bool[365]
数组和索引按第1天
@GhostCat对我来说这听起来像是一个家庭作业问题:类似于“通过模拟小组经验验证生日悖论的数学分析。”这可能会有帮助。没有解释…没有更新投票。好的答案不仅仅是工作代码!我要发布的是,但是ArrayList.contains是O(n),所以这实际上并没有改变双循环:说“把这个改成那个”…不是一种解释。尤其是当您的代码最终执行相同的操作时。您知道,List.contains()与Set.contains()不是“相同”的。您只是将该内部循环放在某个方法调用中…但隐藏某些内容并不等于消除它。问题是:“如何在不使用嵌套循环的情况下解决它?”在那之后,他提到他在谈论数组列表或散列,然后,你可以推断他指的是寻找重复的代码,答案是正确的,即使你想让StackOverflow中的第一个商业广告真正要问的问题变得更复杂…@RicardoOrtegaMagañI使用了上述代码,但autograder仍然超时。但就我看来,解决方案是完全正确的(2.71%)当我在eclipse和BlueJ中运行它时,我不知道autograder有什么问题。我试过运行这段代码,但值与实际答案相差不大。对于5个人和10000个模拟,我得到的概率是2.73%,但应该正好是2.71%。我编辑过,一旦遇到匹配,就从组中分离出来……听起来可能是这样问题。如果分子是至少有一个匹配的总组,分母是总组,那么上面的代码现在应该可以工作了。完美的解决方案。
public double calculate(int size, int count) {
int numTrialSuccesses = 0;
int[] daysOfYear = new int[365];
final int[] empty = new int[365];
// Repeat and count.
for (int n = 0; n < count; n++) {
Random rand = new Random(n);
// Efficiently clear out the array
System.arraycopy(empty, 0, daysOfYear, 0, 365);
boolean matchExists = false;
for (int i = 0; i < size; i++) {
int birthday = rand.nextInt(365);
// Compare, then increment, the bucket for the birthday
if(daysOfYear[birthday]++>0){
matchExists = true;
break;
}
}
if (matchExists) {
numTrialSuccesses++;
}
} //end-for-trials
double prob = ((double) numTrialSuccesses * 100) / (double) count;
return prob;
}