算法,从包含n个元素的列表中查找组合

时间:2015-04-24 09:49:27

标签: java python c algorithm combinations

我想编写一个函数来从n元素列表中选择k元素的组合。我有pdf格式的给定源文件,我在文本中转换。我得到以下列表。我试图使用{{ 1}}找到组合,但有一些需要先管理的约束,令我困惑。我们需要从下面的列表中选择3个主题。在以下行中dfs表示应选择/这些主题中的任何一个。约束是数学不能与孟加拉语或印地语任何组合。  一些有效的组合是

Ex.from a)History or Sociology or Economics

列表的快照 -

                                 History,Bengali,Sanskrit
                                 Bengali,Philosophy,English

总共3个主题组合将类似a) History/Sociology/Economics b) Bengali/Hindi c) Sanskrit/Mathematics d) Philosophy e) Political Science f) English (来自我的计算) 我正在考虑一种表示列表的方法,以便我可以有效地编写代码。但是无法找到解决这个问题的合理方法。 这是我的实现

(6C3*3*2*2)-24

如果列表变得越来越大然后如何处理输出会有多大,那么复杂性会增加并最终会失败 是否有任何优雅的方法可以使用任何语言的预定义语言数据结构来解决这个问题

1 个答案:

答案 0 :(得分:1)

这里有一个建议:整理您的数据,使其成为一个列表列表:主列表代表组,子列表代表每个组中的主题。

subjects = [
    ["History", "Sociology", "Economics"],
    ["Bengali", "Hindi"],
    ["Sanskrit", "Mathematics"],
    ["Philosophy"],
    ["Political Science"],
    ["English"]
]

然后进行三个嵌套步骤:

  • 首先,生成所有3项组合,例如' {a,b,e}'。你可以look for a good algorithm on SO或自己动手。假设你的一组组很小,你可以只迭代从0到63的整数,并考虑所有正好设置三位的数字。设置位j后,组j将包含在组合中。

  • 现在您有一个包含三个组的列表。在这些列表中构建主题的Cartesian product。由于您正在处理三个列表,因此这应该只是一个三重嵌套循环。

  • 现在你有三个科目。这些主题可能违反了单一的剩余约束条件,即您不能同时使用数学和孟加拉语或印地语中的一个。手动检查此约束并将主题组合添加到您的集合中。

对于它的价值,这里有一个快速而肮脏的C实现,它将用C ++编译:

#include <stdlib.h>
#include <stdio.h>

#define SUBJECT(X)                                          \
    X(History) X(Sociology) X(Economics) X(Bengali)         \
    X(Hindi) X(Sanskrit) X(Mathematics) X(Philosophy)       \
    X(PolScience) X(English)

#define ENUM(X) X,
#define STR(X) #X,

enum {SUBJECT(ENUM) None = -1};
const char *subject[] = {SUBJECT(STR) NULL};

int has(int *grp, int sub)
{
    if (*grp++ == sub)  return 1;
    if (*grp++ == sub)  return 1;
    if (*grp++ == sub)  return 1;

    return 0;
}

int main()
{
    int choice[6][4] = {
        {History, Sociology, Economics, None},
        {Bengali, Hindi, None},
        {Sanskrit, Mathematics, None},
        {Philosophy, None},
        {PolScience, None},
        {English, None},
    };
    int i;

    for (i = 0; i < 64; i++) {
        int *grp[6];
        int n = 0;
        int k, l, m;

        for (m = 0; m < 6; m++) {
            if (i & (1 << m)) grp[n++] = choice[m];
        }

        if (n != 3) continue;

        for (k = 0; grp[0][k] != None; k++) {
            for (l = 0; grp[1][l] != None; l++) {
                for (m = 0; grp[2][m] != None; m++) {
                    int sub[3] = {grp[0][k], grp[1][l], grp[2][m]};

                    if (has(sub, Mathematics) 
                    && (has(sub, Hindi) || has(sub, Bengali))) continue;

                    printf("%s, %s, %s\n", subject[sub[0]], 
                        subject[sub[1]], subject[sub[2]]);
                }
            }
        }        
    }

    return 0;
}