[英]Uniformly divide `n` doubles with a total sum `s`, where each double is below 1 (with proper performance)
我目前正在努力解决这个(代码高尔夫球)挑战 ,并且在给定整数n
和总十进制总和s
(考虑到我们应该支持的范围) ,我很难组合这四个要求: 1 <= n <= 10
和0 <= s <= n
):
n
项目应全部随机,并均匀划分 s
n <= 10
,而不管s
基于这个Stackoverflow答案,我知道如何在给定范围内均匀地划分项目。 例如,在n=5, s=4.5
,我可以创建一个范围为[0, 1.5]
的n-1 = 4
项目的列表,并带有一个额外的前导0
和尾随1.5
。 然后,我可以计算所有差异(因此所有差异的总和将等于s=4.5
)。 这里是一个可能的实现:
int n=5; double s=4.5;
double[] randomValues = new double[n+1];
randomValues[n] = s;
for(int i=1; i<n; i++)
randomValues[i] = Math.random()*s;
java.util.Arrays.sort(randomValues);
System.out.println("Random values:\n"+java.util.Arrays.toString(randomValues)+"\n");
double[] result = new double[n];
for(int i=0; i<n; i++)
result[i] = Math.abs(randomValues[i]-randomValues[i+1]);
System.out.println("Result values:\n"+java.util.Arrays.toString(result)+"\n");
double resultSum = java.util.Arrays.stream(result).sum();
System.out.println("Sum: "+resultSum);
System.out.println("Is the result sum correct? "+(s==resultSum?"yes":"no"));
输出示例:
Random values:
[0.0, 1.3019797415889383, 1.9575834386978177, 2.0417721898726313, 4.109698885802333, 4.5]
Result values:
[1.3019797415889383, 0.6556036971088794, 0.08418875117481361, 2.0679266959297014, 0.39030111419766733]
Sum: 4.5
Is the result sum correct? yes
以上符合上述四个要求中的三个(1、2和4)。 但是,不是3。
我可以在其周围包裹一个循环,只要result
-array中的一项仍然大于1,该循环就会继续:
for(boolean flag=true; flag; ){
... // Same code as above
flag=false;
for(double d:result)
if(d>1)
flag=true;
}
对于大多数n
和s
来说,这仍然相对较快:
在线尝试 (删除/移动打印以免控制台溢出)
但是,最后有四个//
禁用的测试用例,其预期随机值的平均值接近1
,花费的时间太长(甚至在TIO上60秒后超时)。
所以这是我的主要问题所在。 如何像我一样均匀地划分值,并牢记每个值的[0, 1]
范围,并具有良好的性能? 在顶部的链接代码高尔夫球挑战中,我看到了一些其他编程语言的工作示例,例如Python或JavaScript,但是将较长的代码高尔夫球挑战从一种编程语言移植到另一种编程语言通常不是很简单。
好的,找到了一个基于已经给出的JavaScript答案的解决方案。 如果s*s>n
我将s
更改为ns
并设置一个标志以在结果数组中使用1-diff
而不是diff
。
因此,总计为:
boolean inversedFlag = 2*s>n;
double S = s;
if(inversedFlag)
S = n-S;
double[] result = new double[n];
for(boolean flag=true; flag; ){
double[] randomValues = new double[n+1];
randomValues[n] = S;
for(int i=1; i<n; i++)
randomValues[i] = Math.random()*S;
java.util.Arrays.sort(randomValues);
for(int i=0; i<n; i++){
double diff = Math.abs(randomValues[i]-randomValues[i+1]);
result[i] = inversedFlag ? 1-diff : diff;
}
flag=false;
for(double d:result)
flag |= d>1;
}
System.out.println("Result values:\n"+java.util.Arrays.toString(result)+"\n");
double resultSum = java.util.Arrays.stream(result).sum();
System.out.println("Sum: "+resultSum );
System.out.println("Is the result sum correct? "+(s==resultSum?"yes":"no"));
System.out.println();
System.out.println("--------------------------------------------------");
System.out.println();
现在,我只需要再次打高尔夫球,但这与Stackoverflow问题无关。 :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.