网页
资讯
视频
图片
知道
文库
贴吧
地图
采购
进入贴吧
全吧搜索
吧内搜索
搜贴
搜人
进吧
搜标签
日
一
二
三
四
五
六
签到排名:今日本吧第
个签到,
本吧因你更精彩,明天继续来努力!
本吧签到人数:0
一键签到
成为超级会员,使用一键签到
一键签到
本月漏签
0
次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行
补签
。
连续签到:
天 累计签到:
天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
04月20日
漏签
0
天
算法吧
关注:
30,165
贴子:
58,918
看贴
图片
吧主推荐
视频
游戏
6
回复贴,共
1
页
<<返回算法吧
>0< 加载中...
求助各位软件大佬,如何遍历N位二进制数中有M个1的所有数
只看楼主
收藏
回复
_红烧肉__
新人
1
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
比如4位二进制数中有两个1的所有情况如下
有没什么方便的算法能遍历N位二进制数中有M个1的所有数呢?求助啊,有偿
又一只大大鸟
新人
1
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
免费送了,这个算法的时间复杂度是2的N次方,还有一种写法复杂度为C(M,N),就是有多少数满足,复杂度就是多少,不过代码量多一些就不给你写了
落樱风回雪
名士
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
假设十进制x的二进制采用补码表示。则,
c=x & -x
r=x + c
y=(((r^x)>>2)/c) | r
第一个数好办,把右边的bit设为1即可。因此0011。即十进制3。
代入上面三行代码中,
x=3,二进制为0011。-3的二进制是取反加1(即补码),为1101。
c = 0011 & 1101 = 0001。作用,取出最右一个bit 1。
r = 0011 + 0001 = 0100。作用,最右的一串1变成0。(当然,除此外,有一个进位)
r^x = 0100 ^ 0011 = 0111。作用,取出最右一串bit 1。外加一个进位。(多取了一位)。
((r^x)>>2)/c = (0111 >> 2)/0001= 0001。作用,最右一串bit1中去掉最右的bit 1,并移至最右。(上一步多取了一位,所以右移2位。此外,c也是2的幂,除一下会移到最右)
y=0001 | 0100 = 0101。作用,把除最后一串1的部分,以及进位的bit 1,拼上去。注意上一步中删掉了一个bit 1。因此,总的bit 1数量不变。
即十进制,5。
重复这个步骤,x=5 。
c = 0101 & 1011 = 0001。
r = 0101+0001= 0110。
y=(((0110^0101)>>2)/0001)|0110= (((0011)>>2)/0001)|0110=0110,即十进制6。
重复,x=6
c = 0110 & 1010 = 0010。
r = 0110+0010= 1000。
y=(((1000^0110)>>2)/0010)|1000= (((1110)>>2)/0010)|1000=1001,即十进制9。
重复,x=9。
c=1001&0111=0001。
r=1001+0001=1010。
y=(((1010^1001)>>2)/0001)|1010= (((0011)>>2)/0001)|1010=1010,即十进制10。
重复,x=10。
c=1010&0110=0010。
r=1010+0010=1100。
y=(((1100^1010)>>2)/0010)|1100= (((0110)>>2)/0010)|1100=1100,即十进制12。
至此,依次得到了3,5,6,9,10,12。
假如再重复,x=12。
c=1100&0100=0100。
r=1100+0100=0000。溢出。
—————
其实就三步。找出最右边一串1。把它左边一个0变成1。然后这一串1要减掉一个1,再移到最右(右边没有0)。
如果最右一串1的左边没有0了,那就到头了。再操作就溢出了。
落樱风回雪
名士
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
#include<stdio.h>
int main(int argc, char *argv[])
{
int N=4, M=2;
int x=(1U << M)-1, r,c;
do {
printf("%d\n", x );
c= x & -x;
r= x + c;
x = (((r^x)>>2)/c)|r;
} while (r<(1<<N));
return 0;
}
登录百度账号
扫二维码下载贴吧客户端
下载贴吧APP
看高清直播、视频!
贴吧页面意见反馈
违规贴吧举报反馈通道
贴吧违规信息处理公示