Java:将数字分成等于或相近的部分

时间:2015-09-12 19:25:42

标签: java android numbers integer

我有一个数字= 20.而我想把这个数字分成N等于部分或彼此接近。 N可能是1到20。

我写这段代码:

ArrayList<Integer> c = new ArrayList<>();
int num = 20;
int count = N; //where N some number (from 1 to 20)
int val = (int) Math.floor(num / count);

for (int i = 0; i < count; i++) {
    c.add(val);
}
c.set(0, c.get(0) + num - sum(c));

它工作正常,例如,当count = N = 3时,我得到:8,6,6(8 + 6 + 6 = 20)。但如果count = N = 12,我得到下一个结果:9,1,1,1,1,1,1,1,1,1,1,1(sum = 20)。我想要的结果将是下一个:1,2,2,2,2,2,2,2,1,1,1(总和= 20)。这可能吗?

4 个答案:

答案 0 :(得分:7)

您计算 next 部分的大小,然后减少这些值并重复:

private static int[] splitIntoParts(int whole, int parts) {
    int[] arr = new int[parts];
    int remain = whole;
    int partsLeft = parts;
    for (int i = 0; partsLeft > 0; i++) {
        int size = (remain + partsLeft - 1) / partsLeft; // rounded up, aka ceiling
        arr[i] = size;
        remain -= size;
        partsLeft--;
    }
    return arr;
}

如果你愿意,可以挤压该方法,但如上所述更好,因为它将参数视为不可变的并澄清了逻辑:

private static int[] splitIntoParts(int whole, int parts) {
    int[] arr = new int[parts];
    for (int i = 0; i < arr.length; i++)
        whole -= arr[i] = (whole + parts - i - 1) / (parts - i);
    return arr;
}

测试

for (int parts = 0; parts <= 25; parts++)
    System.out.println(parts + ": " + Arrays.toString(splitIntoParts(20, parts)));

输出

0: []
1: [20]
2: [10, 10]
3: [7, 7, 6]
4: [5, 5, 5, 5]
5: [4, 4, 4, 4, 4]
6: [4, 4, 3, 3, 3, 3]
7: [3, 3, 3, 3, 3, 3, 2]
8: [3, 3, 3, 3, 2, 2, 2, 2]
9: [3, 3, 2, 2, 2, 2, 2, 2, 2]
10: [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
11: [2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1]
12: [2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1]
13: [2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1]
14: [2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1]
15: [2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
16: [2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
17: [2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
18: [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
19: [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
20: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
21: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
22: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0]
23: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
24: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
25: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]

请注意0返回空数组。如果失败,请添加if语句。负值将因NegativeArraySizeException而失败。如您所见,太多部件会简单地返回0大小的部分。如果失败,请添加if语句

答案 1 :(得分:2)

你去吧

#include <iostream>
#include <fstream>


class fstreamtest
{
public:
    std::fstream file;
    fstreamtest()
    {
        std::cout << "fstreamtest constructor" << std::endl;

    }
    ~fstreamtest()
    {
        std::cout << "fstreamtest destructor" << std::endl;
    }
};

void func(fstreamtest t)
{
    (void)t;
}
int main(int argc, char** argv)
{
    (void) argc;
    (void) argv;

    fstreamtest t;

    func(t);
    return 0;
}

答案 2 :(得分:1)

我有一个简单的解决方案(虽然不是最好的) -

int[] parts = new int[count];

int j = 0;
for (int i=1; i<=num; i++) {
    parts[j] += 1;
    j++;
    if (j == count) {
        j = 0;
    }
}

答案 3 :(得分:1)

我稍微修改了你的代码。看看是否有效。

ArrayList<Integer> c = new ArrayList<>();
int num = 20;
int count = 12; //where N some number (from 1 to 20)
int val = (int) Math.floor(num / count);
int sum = 0;
int max = val;
for (int i = 0; i < count; i++) {
    c.add(val);
    sum+=c.get(i);
}

int temp = c.get(0) + num - sum;
int i=1;
while (temp > max) {
    if (i>=c.size())
        i = 1;
    temp-=1;
    c.set(i, c.get(i) + 1);
    if (max < c.get(i))
        max = c.get(i);
    i++;
}
c.set(0, temp);
System.out.println(c);