【问题标题】:k permutation in c++c ++中的k排列
【发布时间】:2013-12-18 11:13:45
【问题描述】:

我正在尝试生成 n 值的所有 k 排列而不重复。 例如,从 3 到 2 个值的排列: 1、2、3

答案是:

1, 2

1、3

2, 1

2、3

3, 1

3、2

我目前正在使用 STL 中的 next_permutation() 来生成所有排列。另外,我找到了一个生成大小 k 组合的代码。代码如下:

res = new vector<vector<int>>;

vector<int> a;

for(int i = 0; i < n; i++)
    a.push_back(i); 

do {
    vector<int> b;

    for(int i = 0; i < k; i++)
        b.push_back(a[i]);

    do {
        res->push_back(b);          
    } while(next_permutation(b.begin(), b.begin() + k));                

} while(next_combination(a.begin(), a.begin() + k, a.end()));

首先,该函数找到一个新组合,然后使用 next_permutation 生成该特定子集的所有排列。

这段代码非常耗时。我想知道是否有更好的库可以在 c++ 中产生 k 排列?

【问题讨论】:

  • 什么是next_combination?代码的有效性很大程度上取决于此函数的有效性。
  • 很好的家庭作业问题,谢谢!
  • 我在网上找到了能正确地从 n 中生成所有大小为 k 的组合(子集)的函数。
  • 您应该知道,您尝试打印的枚举列表具有阶乘时间复杂度。您正在查看的 N 和 K 的大小是多少?
  • @IvayloStrandjev 这是一个标准库函数(对于 OP 的问题,它是错误的)。

标签: c++ algorithm permutation


【解决方案1】:

std::next_permutation 库函数按字典顺序生成排列。它的复杂度高达列表大小的一半。

您可以使用递归自己实现代码。这也不是有效的,因为这种组合的数量具有阶乘复杂性。此外,您还冒着用完所有堆栈空间的风险。

void recurCombinations( vector<int> &soFar, vector<int> &remaining, int K ) {
  if ( soFar.size() == K ) {
    output( soFar );
    return;
  }

  for ( int j = 0; j < remaining.size(); j++ ) {
    vector<int> newRemaining( remaining );
    vector<int> newSoFar( soFar );
    newSoFar.push_back( remaining[ j ] );
    newRemaining.erase( newRemaining.begin() + j );
    recurCombinations( newSoFar, newRemaining, K );
  }

}

【讨论】:

  • 感谢您的代码。这似乎很耗时,并且可能没有更好的方法来降低复杂性。我尝试两者都找到更好的。
  • @user2165341 让我指出,任何解决方案都会执行至少choose(n, k) * k! 数量级的操作(即,我们可以通过多少种方式从 n 中选择 k 个元素)。这意味着 k 不能很大(例如,对于 k = 30,您将至少执行 265252859812191058636308480000000 - 远远超过您在任何合理时间内能够执行的次数。
  • @AbhishekBansal 我没有仔细阅读您的答案。对不起。我认为这是一个很好的解决方案
  • 是的,我同意你的看法。但是,在我的问题中,k 非常小(小于 5),但 n 却很大。所以,next_combination 应该更高效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 2018-05-16
  • 2017-01-18
  • 2021-07-01
相关资源
最近更新 更多