查找2D阵列每行中1个元素的所有可能组合

时间:2016-12-17 21:12:38

标签: c++ arrays combinations

最近我一直试图做一个问题,要求我找到所有不同的组合,每行只选择1个元素。例如,我输入n行,每行2个字符串。但是,我只想找到所有不同的组合,我从每行中选择1个字符串。

示例:

输入:

3
alex bob
straw mat
eat drink

示例组合: 亚历克斯秸秆饮料

这导致2 ^ n个组合,在这种情况下将是2 ^ 3 = 8个组合。但是,如果我使用n for循环来查找组合 例如

#include <iostream>
#include <cstring>
#include <string>

using namespace std;
int n;
int main(int argc, char ** argv) {

    cin >> n; //rows of words
    string words[n][2]; //the words with 2 words per row

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 2; j++) {
            cin >> words[i][j]; //input of words
        }
    }
    //finding all possible combinations
    for (int i =0; i<n; i++){
        for (int j=0; j<2; j++){
            for (int x=0; x<2; x++){
                //and so on per n
            }
        }
    }
    return 0;
}

这将需要n for循环来找出数组的所有组合,只从每一行中取一个项目。什么是最好和最简单的方法来找到大小为n的所有不同组合,因为我会从每行中的两个中取1个字符串?感谢。

3 个答案:

答案 0 :(得分:2)

你可以做递归。

假设C ++ 11,这样的事情可能(虽然没有尝试编译):

// finding all possible combinations
std::vector<std::vector<std::string>> combinations;

const auto processLine = [&](const std::vector<std::string>& currentCombination, int line) {    

    std::vector<std::string> combination0 = currentCombination;
    std::vector<std::string> combination1 = currentCombination;
    combination0.push_back(words[line][0]);
    combination1.push_back(words[line][1]);

    if (line + 1 < n) {
        // process next line
        processLine(combination0, line + 1);
        processLine(combination1, line + 1);
    }
    else {
        // last line - keep the result
        combinations.push_back(combination0);
        combinations.push_back(combination1);
    }
};

std::vector<std::string> empty;
processLine(empty, 0);

// print results
for (const auto& combination : combinations) {
    for (const auto& word : combination) {
        std::cout << word << " ";
    }
    std::cout << std::endl;
}

答案 1 :(得分:1)

对于每行总有2个元素的设置,一个非常简单的解决方案是使用数据类型整数并将每个位解释为相应行中第一列或第二列的决策;然后简单地从0到2 ^ n - 1计数以获得所有组合。 应用于您的示例,如下所示:

int bits meaning
0   000  alex,straw,eat
1   001  alex,straw,drink
2   010  alex,mat,eat
3   011  alex,mat,dring
4   100  bob,straw,eat
5   101  bob,straw,drink
6   110  bob,mat,eat
7   111  bob,mat,drink

对于任何给定的整数值0..7,使用位移运算符或&amp; -bitmask将每个位映射到列索引:

void getCombinationRepresentedByIntValue(vector<string>& combination, int value) {  
  int mask = 1;
  for (int i=n-1; i>=0; i--) {
     if (value & mask)
       combination.push_back(words[i][1]);
     else
       combination.push_back(words[i][0]);
     mask = mask << 1;
  }   
}

答案 2 :(得分:0)

这似乎回答了你的问题:

    int ct[n]; // count of the number of pass 
    int current = 0; // index of the current word (n)

    /* while not all combinaison have been exploited */
    while (current >= 0)
    {
        cout << words[current][ct[current]];  /* <<<<< can be used another way*/
        /* down to the next word */
        current ++; // to get the next word
        if (current >=n) { // at the end of the list
            cout << " ";
            current--; // restore last
            ct[current]++; // increment number of time we passed
            /* find the previous not completely exploited */
            while (current >= 0 && ct[current]> 1) /* <<< change 1 to any number of words per line */
            {
                ct[current] = 0;
                current--;
                if (current >= 0) ct[current]++;
            }
            if (current > 0 ) current = 0;
        }
    }

用你的例子:

输入:

3 亚历克斯鲍勃 草席 吃喝?

输出: alexstraweat alexstrawdrink alexmateat alexmatdrink bobstraweat bobstrawdrink bobmateat bobmatdrink

希望它有所帮助!