我有一个问题,我不知道如何解决它。
我有一个二进制字符串,我想生成所有可能的二进制子串。
示例:
input : 10111
output: 10000, 10100,00111,00001,10110 ...
我怎样才能做到这一点,快速而聪明?
答案 0 :(得分:6)
Magic - 虽然假设了bitmask:
subset( int x )
list = ()
for ( int i = x; i >= 0; i = ( ( i - 1 ) & x ) )
list.append( i )
return list
你可以使用相同的逻辑,虽然它涉及更多,使用二进制字符串。
答案 1 :(得分:2)
没关系 - 该死的我忘了你用字符串而不是int / long / what。你仍然可以使用相同的逻辑...只计算二进制,但只使用包含1的位置。
大声思考。
我们取字符串1001
我想,你想要的是四个数字1001,1000,0001和0000,是吗?
如果是这样,你正在做的是计算“那些”的位置。
一种方法是存储原始号码
orig = n;
然后开始迭代那个和每个较低的数字
while(n--)
但是每次迭代都会忽略试图将1放在0位置的那些:
if(n & !orig)
continue;
如果你期望它是稀疏的 - 就像很少有1的零那样,你可以使用移位机制。所以我们说你的号码是1000 1001
注意有三个1,对吗?所以只计算从000到111
但是对于每次迭代,再次将这些位分散开来:
n& 0000 0001 | n<< 2& 0000 1000 | n<< 5& 1000 0000
或另一种思考方式:
n& 001 | (n& 010)* 1000 | (n& 100)* 1000 000
这可能比其他解决方案慢,这取决于出现了多少1,因为它涉及内部循环,原始数字中的每个1都有1次迭代。
很抱歉在二进制和十进制之间转换 - 如果您愿意,我可以用十六进制全部完成:)
现在我无法想出一个直接映射位而不移位的模式 - 这样效果最好。
答案 2 :(得分:1)
使用递归
printsubsets(const string &in, const string &out)
{
if(in.empty())
{
cout<<out<<"\n";
return;
}
if(in[0]=='1')
printsubsets(in.substr(1), out+"1");
printsubsets(in.substr(1), out+"0");
}
答案 3 :(得分:1)
这样做:
vector<string> submasks(string in)
{
vector<string> out;
out.push_back(string(in.size(), '0'));
for (int i = 0; i < in.size(); ++i)
{
if (in[i] == '0') continue;
int n = out.size();
for (int j = 0; j < n; ++j)
{
string s = out[j];
s[i] = '1';
out.push_back(s);
}
}
return out;
}
算法执行此操作:
我认为这非常优秀。
答案 4 :(得分:0)
这类问题出现在那些代码katcha网站上