1)/2的数字

8cdiaqws  于 2021-07-03  发布在  Java
关注(0)|答案(3)|浏览(323)

**结束。**此问题不符合堆栈溢出准则。它目前不接受答案。
**想改进这个问题吗?**更新问题,使其成为堆栈溢出的主题。

上个月关门了。
改进这个问题
我需要得到一个由n个整数组成的数组,从0到n-1,这样所有整数的和就是n(n-1)/2。我该怎么做?
我尝试这样做的一种方法是随机选取前n-1个数字,然后选取最后一个数字,这样的总和就是n(n-1)/2。如果它在区间[0,n-1],那么我是好的。否则,我将递归地再次运行相同的函数。但是,当我运行这个时,我得到了一个stackoverflow错误,因为递归运行了太多次(我创建的列表都不起作用)。
有没有更好的方法在java中随机生成这样的列表?

hs1ihplo

hs1ihplo1#

尝试从0到n-1的整数。设n=6

0 1 2 3 4 5     
n(n-1)/2 = 6(6-1)/2 = 6(5)/2 = 15
6yjfywim

6yjfywim2#

简单的解决方案是创建列表0到n-1(0到n-1的和是 n(n - 1) / 2 .)
如果你想要一个随机化的列表,把上面的列表洗牌。
如果您想要一个随机化的列表,而不仅仅是列表0到n-1的排列:
从上面的列表0到n-1开始
洗牌列表。
重复(直到达到所需的随机性水平)执行以下操作:
随机选择两个现有的列表元素:a和b
生成一个随机数r,使得a+r<n和b-r>=0
a'<-a+r
b'<-b-r
这可以在 O(n) 操作。。。取决于结果的随机性。
(我不确定你需要重复步骤3多少次才能获得“足够”的随机性,但我认为应该是这样 O(n) 次。)

ccrfmcuu

ccrfmcuu3#

一种解决方案:

import java.lang.Math;

...

public int[] solution(int n) {
    int[] solution = new int[n];
    int targetSum = (n * (n - 1)) / 2;
    int runningSum = 0;
    double avgRemainder = 0.0;
    for (int i = 0; i < n - 1; i++) {
        do {
            solution[i] = (int)(Math.random() * n);
            avgRemainder = (targetSum - runningSum - solution[i])/(n - (i + 1));
            if (avgRemainder >= 0.0 && avgRemainder <= (n - 1)) {
                runningSum += solution[i];
            }
        } while (!(avgRemainder >= 0.0 && avgRemainder <= (n - 1)));
    }
    solution[n - 1] = targetSum - runningSum;
    return solution;
}

这将生成一个随机数,但在将其添加到解决方案列表之前,它将检查是否会导致剩余插槽的平均值超出可接受的数字范围,包括超出目标和。
这种方法的缺点(尤其是在顺序重要的情况下)是,它会导致最后的漏斗,如果你在开始时随机生成大量的数字,那么很明显,剩余的数字会循环,直到它们足够小,适合解决方案。。。例如:
如果n=5
如果我们随机生成前两个数字为4
[4, 4, ?, ?, ?]
然后这个方法将循环第三个随机数,直到它介于0和2之间,如果它是2。。。
[4, 4, 2, ?, ?]
然后它将循环剩余的数字,直到它们为0。
[4, 4, 2, 0, 0]
对于较大的n值,这应该很好,并且它是迭代的而不是递归的。
编辑:所以实际上最后一项必须强制执行,因为解决方案[n-1]只有一个解决方案。我修复了上面的代码来添加它,因为它在线程“main”java.lang.arithmeticexception:/中得到了一个:exception。

相关问题