假设我有一个大小为v = {0, 1,..., N-1}
的整数N
向量。
如果大小为k
,我想生成所有k
大小的v
组合。
for example: k = 2, N = 10
{0,1}, {0,2}, ..., {0,9}, {1,2}, ..., {8,9}
但我想逐个使用名为NextCombination
的方法:
bool NextCombination(vector<int>& v, int k, int N){
if( is not the last combination){
turn v into it's next combination
return true;
}
return false;
}
这意味着,鉴于当前状态v
,组合的大小k
和元素总数,我想更改v
(如果可能) )并返回bool
,表示可以从v
中获得下一个组合。
如果没有一些无聊的递归,我无法弄清楚如何做到这一点,因为这只是我正在做的事情的小问题,我想找出一些智能/小解决方案。
答案 0 :(得分:2)
您标记了C ++,因此最简单的方法是 - 使矢量长度为N,包含K个和(N-K)个零,如{1,1,0,0,0}
并应用std::next_permutation。
在每个步骤的位置显示 - 应该采取什么数字组合。
例如,排列{0,1,0,1,0}
对应(1,3)
组合。
修改强>
来自JörgArndtMatters Computational book的代码使用现成的K长度数组(格式和可读性差)
void first()
{
for (ulong k=0; k<k_; ++k) x_[k] = k;
}
ulong next()
// Return smallest position that changed, return k with last combination
{
if ( x_[0] == n_ - k_ ) // current combination is the last
{ first(); return k_; }
ulong j = k_ - 1;
// easy case: highest element != highest possible value:
if ( x_[j] < (n_-1) ) { ++x_[j]; return j; }
// find highest falling edge:
while ( 1 == (x_[j] - x_[j-1]) ) { --j; }
// move lowest element of highest block up:
ulong ret = j - 1;
ulong z = ++x_[j-1];
// ... and attach rest of block:
while ( j < k_ ) { x_[j] = ++z; ++j; }
return ret;
}
答案 1 :(得分:1)
然而,如果你真的想节省内存,那么你需要制作一个1和0的N大小的矢量。 以下解决方案基本上就地做了相同的事情。
bool NextCombination(vector<int>& v, int k, int N) {
// We want to find the index of the least significant element
// in v that can be increased. Let's call that index 'pivot'.
int pivot = k - 1;
while (pivot >= 0 && v[pivot] == N - k + pivot)
--pivot;
// pivot will be -1 iff v == {N - k, N - k + 1, ..., N - 1},
// in which case, there is no next combination.
if (pivot == -1)
return false;
++v[pivot];
for (int i = pivot + 1; i < k; ++i)
v[i] = v[pivot] + i - pivot;
return true;
}