解决错误生成组合问题的非递归方法
我想要一种非递归方法来解决生成某些字符或数字集的组合的问题。
因此,给定数字 n 的子集 k,生成所有可能的组合 n!/k!(nk)!
给定前一个组合,递归方法将给出一个组合。
非递归方法将生成给定循环索引值i的组合。
我用这段代码解决了这个问题:
用 n = 4 和 k = 3 进行测试,它可以工作,但是如果我将 k 更改为数字 > 3它不起作用。
是因为(nk)!在n=4并且k=3的情况下是1。并且如果k>1。 3会大于1吗?
谢谢。
int facto(int x);
int len,fact,rem=0,pos=0;
int str[7];
int avail[7];
str[0] = 1;
str[1] = 2;
str[2] = 3;
str[3] = 4;
str[4] = 5;
str[5] = 6;
str[6] = 7;
int tot=facto(n) / facto(n-k) / facto(k);
for (int i=0;i<tot;i++)
{
avail[0]=1;
avail[1]=2;
avail[2]=3;
avail[3]=4;
avail[4]=5;
avail[5]=6;
avail[6]=7;
rem = facto(i+1)-1;
cout<<rem+1<<". ";
for(int j=len;j>0;j--)
{
int div = facto(j);
pos = rem / div;
rem = rem % div;
cout<<avail[pos]<<" ";
avail[pos]=avail[j];
}
cout<<endl;
}
int facto(int x)
{
int fact=1;
while(x>0) fact*=x--;
return fact;
}
I wanted a non recursive approach to the problem of generating combination of certain set of characters or numbers.
So, given a subset k of numbers n, generate all the possible combination n!/k!(n-k)!
The recursive method would give a combination, given the previous one combination.
A non recursive method would generate a combination of a given value of loop index i.
I approached the problem with this code:
Tested with n = 4 and k = 3, and it works, but if I change k to a number > 3 it does not work.
Is it due to the fact that (n-k)! in case of n = 4 and k = 3 is 1. and if k > 3 it will be more than 1?
Thanks.
int facto(int x);
int len,fact,rem=0,pos=0;
int str[7];
int avail[7];
str[0] = 1;
str[1] = 2;
str[2] = 3;
str[3] = 4;
str[4] = 5;
str[5] = 6;
str[6] = 7;
int tot=facto(n) / facto(n-k) / facto(k);
for (int i=0;i<tot;i++)
{
avail[0]=1;
avail[1]=2;
avail[2]=3;
avail[3]=4;
avail[4]=5;
avail[5]=6;
avail[6]=7;
rem = facto(i+1)-1;
cout<<rem+1<<". ";
for(int j=len;j>0;j--)
{
int div = facto(j);
pos = rem / div;
rem = rem % div;
cout<<avail[pos]<<" ";
avail[pos]=avail[j];
}
cout<<endl;
}
int facto(int x)
{
int fact=1;
while(x>0) fact*=x--;
return fact;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
呃..为什么不使用
std::next_permutation
?它完全可以满足您的需求,并且不需要您自己编写(以及调试和维护)。Err.. why not use
std::next_permutation
? It does exactly what you're looking for and doesn't require you to write (and debug and maintain) your own.这大约是可以计算的速度 - 实际的组合函数是使用两行代码完成的。
然而,这并不是最直观、最容易理解的!
这项工作是通过实施格雷码序列来完成的。
This is about as fast as it can be calculated - the actual combination function is done using two lines of code.
However, this isn't the most intuitively easy to understand!
The work is done by implementing a Gray code sequence.
假设您的迭代器是以 n 为基数的 k 位数字。在 C/C++ 中,您可以将其表示为大小为 k 的
int
数组,其中每个元素的范围为0
到n-1
)。然后,要从一个位置迭代到下一个位置,只需增加数字即可。
这将为您提供所有排列。为了获得组合,您必须施加一个附加条件,即数字必须按升序排列。
例如,使用
k = 3, n = 3: 000 001 002 011 012 022 111 112 122 222
在 C 中实现该约束也非常简单,在用于迭代的增量操作上,而不是设置当有进位时,最右边的数字为零,您必须将它们设置为与最左边的数字更改相同的值。
更新:一些代码:
Consider that your iterator is a number of k digits in base n. In C/C++ you can represent it as an array of
ints
of size k where every element is in the range from0
ton-1
).Then, to iterate from one position to the next you only need to increment the number.
That will give you all the permutations. In order to get combinations you have to impose an additional condition that is that digits must be in ascending order.
For instance with
k = 3, n = 3: 000 001 002 011 012 022 111 112 122 222
Implementing that constraint in C is also pretty simple, on the increment operation used to iterate, instead of setting the rightmost digits to zero when there is a carry, you have to set them to the same value as the leftmost digit changed.
update: some code: