将列表分组的算法

时间:2012-01-12 14:29:35

标签: java algorithm list data-partitioning

我有一个名单。

我想将此列表分区为指定大小的组。所有组应该等于或小于指定的大小,组中的组大小尽可能相等,并且尽可能接近指定的大小。

什么算法(如果可能,请使用Java-esque伪代码!)确定最合适的组大小?

例如:

列表包含13个名称 - 最大团队规模3。 输出(组大小):3,3,3,2,2

列表包含13个名称 - 最大团队规模4。 输出:4,3,3,3

列表包含31个名称 - 最大团队规模5。 输出:5,5,5,4,4,4,4

列表包含31个名称 - 最大团队规模6。 输出:6,5,5,5,5,5

列表包含31个名称 - 最大团队规模10。 输出:8,8,8,7

4 个答案:

答案 0 :(得分:4)

这很简单。您计算N div M的结果并添加1以获得正确的数组数(N是列表长度,M是最大团队大小),然后迭代所有数组以添加项目,直到用完项目为止

示例:43个名称,最大团队编号4 => 43 mod 4 + 1 = 11,保持为3.所以11个阵列(10个有4个,1个有3个)

答案 1 :(得分:2)

我不会为此编写代码,但是

  1. 如果列表大小是最大团队规模的倍数,则除以团队规模以获得组数,所有最大规模和停止。
  2. 整数除以最大团队规模的列表大小,然后添加一个。这就是团体数量。
  3. 从下一个更高的倍数中减去列表大小;这是一个比最大尺寸小一个的团队数量。
  4. 这显然只适用于接近锻炼的输入;如果最大团队规模与列表规模相比较大,则会失败。

答案 2 :(得分:2)

如果列表中的项目数为N且子列表中的最大项目数为K,则问题的解决方案来自求解Linear Diophantine Equation

K*x + (K-1)*y = N

有其他约束

x > 0
y >= 0

其中x是确切大小K的子列表数量,y是长度为K-1的子列表数量。

编辑:由于等式的系数总是相互偏离,因此解决方案非常简单:

int m = (N+K-1)/K;
int x = N - (K-1)*m; // Number of "full" lists
int y = K*M - N;     // Number of off-by-one lists

示例1:

N = 31, K = 5
m = (31+5-1)/5 = 7
x = 31 - (5-1)*7 = 3 // 3 lists of 5 items
y = 5*7 - 31 = 4     // 4 lists of 4 items

示例2:

N = 32, K = 4
m = (32+4-1)/4 = 8
x = 32 - (4-1)*8 = 8 // 8 lists of 4 items
y = 4*8 - 32 = 0     // no lists of 3 items

查找一个在网上求解线性丢番图方程的算法 - 如果你理解Euclidean algorithm那就不那么复杂了。没有约束的方程的解的数量是无限的,但是一旦你添加约束,你应该得到一个解决方案。

答案 3 :(得分:0)

public class Q {
public static void q(int size, int maxTeamSize) {
    int numOfTeams = size / maxTeamSize;
    int mod = size % maxTeamSize;
    numOfTeams += (mod > 0) ? 1 : 0;
    System.out.print("\n(" + size + ":" + maxTeamSize + ")");
    for (int i = 0; i < numOfTeams; i++) {
        System.out.print(" " + (size / numOfTeams + ((i < mod) ? 1 : 0)));
    }
}

public static void main(String[] args) {
    q(13, 3);
    q(12, 4);
    q(31, 5);
    q(31, 6);
}
}