【问题标题】:Algorithm to partition a list into groups将列表划分为组的算法
【发布时间】:2012-01-12 14:29:35
【问题描述】:

我有一个名字列表。

我想将此列表划分为指定大小的组。所有组应等于或小于指定大小,各组之间的组大小应尽可能相等,并尽可能接近指定大小。

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

例如:

列表包含 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

【问题讨论】:

  • 这是作业吗?你试过什么?
  • 1,1,1,1,1,1,1,1,1,1,1,1,1 在每个组中也最多有 3 个项目,并且组大小比你的榜样。
  • 预期输出不清楚。例如,输出是什么: List contains 31 names - max team size 10

标签: java algorithm list data-partitioning


【解决方案1】:

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

示例:43 个名称,最大团队编号 4 => 43 mod 4 + 1 = 11,仍然是 3。所以 11 个数组(10 和 4,1 和 3)

【讨论】:

  • 您的意思可能是div,而不是mod,因为43 mod 43,而不是10mod 表示余数,而不是整数除法)。如果 M 除以 N 而没有余数,+1 也将不起作用。你需要(N+M-1) div M 才能得到你想要的结果。
  • 我认为这个答案很简单,以至于我忽略了它作为解决方案。 :)
【解决方案2】:

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

  1. 如果列表大小是最大团队大小的倍数,则除以团队大小以获得组数、最大大小,然后停止。
  2. 将列表大小除以最大团队大小,然后加一。这就是组的数量。
  3. 从下一个更高的倍数中减去列表大小;这是比最大规模小 1 的团队数量。

这显然只适用于接近锻炼的输入;如果与列表的大小相比,最大团队规模较大,则会失败。

【讨论】:

    【解决方案3】:

    如果列表中的项目数为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 好,它并不复杂。没有约束的方程解的数量是无限的,但是一旦添加了约束,你应该得到一个解。

    【讨论】:

    • 我认为算法会根据示例有所改变,列表为 31,最大大小为 10。
    【解决方案4】:
    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);
    }
    }
    

    【讨论】:

    • 这是一个简洁的算法,但会产生更多的小数字组。我的目标是让尽可能多的团队尽可能接​​近最大团队规模。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    相关资源
    最近更新 更多