如何在长度为n的位数组中生成所有可能的位组合。如果我从数组中的所有零开始,则有n种可能性放置第一位,对于这n种可能性,有n-1种可能性来放置第二位。单位所有n位都设置为1。但到目前为止,我没有设法编制它。
也有很多人指出我可以通过从0到(2 ^ n)-1计数并以二进制打印数字来做到这一点。这将是解决问题的简单方法,但是在这种情况下,我只是让机器计数而不是告诉它放置在哪里。我是为了学习而这样做的,所以我想知道如何编制一个放置方法。
答案 0 :(得分:13)
您如何在纸上手动计算?你会检查最后一位数。如果为0,则将其设置为1.如果已经为1,则将其设置为0并继续下一个数字。所以这是一个递归过程。
以下程序通过改变序列来生成所有可能的组合:
#include <iostream>
template <typename Iter>
bool next(Iter begin, Iter end)
{
if (begin == end) // changed all digits
{ // so we are back to zero
return false; // that was the last number
}
--end;
if ((*end & 1) == 0) // even number is treated as zero
{
++*end; // increase to one
return true; // still more numbers to come
}
else // odd number is treated as one
{
--*end; // decrease to zero
return next(begin, end); // RECURSE!
}
}
int main()
{
char test[] = "0000";
do
{
std::cout << test << std::endl;
} while (next(test + 0, test + 4));
}
该程序适用于任何类型的任何序列。如果您需要同时进行所有可能的组合,只需将它们放入集合中而不是将它们打印出来。当然,您需要一个不同的元素类型,因为您不能将C数组放入向量中。让我们使用字符串向量:
#include <string>
#include <vector>
int main()
{
std::vector<std::string> combinations;
std::string test = "0000";
do
{
combinations.push_back(test);
} while (next(test.begin(), test.end()));
// now the vector contains all pssible combinations
}
如果你不喜欢递归,这里是一个等价的迭代解决方案:
template <typename Iter>
bool next(Iter begin, Iter end)
{
while (begin != end) // we're not done yet
{
--end;
if ((*end & 1) == 0) // even number is treated as zero
{
++*end; // increase to one
return true; // still more numbers to come
}
else // odd number is treated as one
{
--*end; // decrease to zero and loop
}
}
return false; // that was the last number
}
答案 1 :(得分:10)
这些问题在功能上很容易解决。要找到长度为n的解,首先找到长度为n-1的解,然后将“0”和“1”附加到这些解,使解空间加倍。
这是一个简单的递归Haskell程序:
comb 0 = [[]]
comb n =
let rest = comb (n-1)
in map ('0':) rest
++ map ('1':) rest
这是一个测试运行:
> comb 3
["000","001","010","011","100","101","110","111"]
答案 2 :(得分:1)
C ++中的“真正”递归方法:
#include <iostream>
#include <string>
void print_digits(int n, std::string const& prefix = "") {
if (!n) {
std::cout << prefix << std::endl;
return;
}
print_digits(n-1, prefix + '0');
print_digits(n-1, prefix + '1');
}
int main(int, char**) {
print_digits(4);
}
答案 3 :(得分:1)
答案 4 :(得分:1)
这是我的答案。优点是所有组合都保存在二维数组中,但缺点是你只能使用它来获得长达17位的刺痛!
#include <iostream>
using namespace std;
int main()
{
long long n,i1=0,i2=0, i=1, j, k=2, z=1;
cin >> n;
while (i<n){
k = 2*k;
i++;
}
bool a[k][n], t = false;
j = n-1;
i1=0;
i2 = 0;
z = 1;
while (j>=0){
if(j!=n-1){
z=z*2;
}
i2++;
t = false;
i = 0;
while (i<k){
i1 = 0;
while (i1<z){
if(t==false){
a[i][j]=false;
}
else {
a[i][j]= true;
}
i1++;
i++;
}
if(t==false){
t = true;
}else {
t = false;
}
}
j--;
}
i = 0;
j = 0;
while (i<k){
j = 0;
while (j<n){
cout << a[i][j];
j++;
}
cout << endl;
i++;
}
return 0;
}
答案 5 :(得分:0)
FredOverflow一般都是正确的。
然而,1s&amp; 0s你最好只从0增加一个整数:
int need_digits = 10
unsigned int i=0
while (! i>>need_digits){
# convert to binary form: shift & check, make an array, or cast to string, anything.
}
...我想你不需要超过32位,或者你必须链接多个整数..并坚持前面的答案:)