我将n个元素存储在一个数组中,并且在n(n个选择k)上有k个可能的子集。
我必须在长度为n的数组中找到k个元素的所有可能组合,并针对每个集合(长度为k),对所选元素进行一些计算。

我写了一个递归算法(在C++中),可以很好地工作,但对于大量算法,它会崩溃而耗尽堆空间。

我该如何解决该问题?如何计算n和k大的所有n个集合?
有C++库可以帮助我吗?

我知道这是一个np问题,但是我会写最好的代码以便计算最大数目。

除了变得不可行之外,最大的数字(n和k)大约是多少?

我只要求最好的算法,而不要求不可行的空间/工作。

这是我的代码

vector<int> people;
vector<int> combination;

void pretty_print(const vector<int>& v)
{
    static int count = 0;
    cout << "combination no " << (++count) << ": [ ";
    for (int i = 0; i < v.size(); ++i) { cout << v[i] << " "; }
        cout << "] " << endl;
}

void go(int offset, int k)
{
    if (k == 0) {
        pretty_print(combination);
        return;
    }
    for (int i = offset; i <= people.size() - k; ++i) {
        combination.push_back(people[i]);
        go(i+1, k-1);
        combination.pop_back();
    }
}

int main() {
    int n = #, k = #;

    for (int i = 0; i < n; ++i) { people.push_back(i+1); }
        go(0, k);

    return 0;
}

最佳答案

这是非递归算法:

const int n = ###;
const int k = ###;

int currentCombination[k];
for (int i=0; i<k; i++)
    currentCombination[i]=i;
currentCombination[k-1] = k-1-1; // fill initial combination is real first combination -1 for last number, as we will increase it in loop

do
{
    if (currentCombination[k-1] == (n-1) ) // if last number is just before overwhelm
    {
        int i = k-1-1;
        while (currentCombination[i] == (n-k+i))
            i--;

        currentCombination[i]++;

        for (int j=(i+1); j<k; j++)
            currentCombination[j] = currentCombination[i]+j-i;
    }
    else
        currentCombination[k-1]++;

    for (int i=0; i<k; i++)
        _tprintf(_T("%d "), currentCombination[i]);
    _tprintf(_T("\n"));

} while (! ((currentCombination[0] == (n-1-k+1)) && (currentCombination[k-1] == (n-1))) );

关于c++ - N为大n和k选择k,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19327847/

10-13 03:32