算法之位运算

之前我是写过一个位运算的博客的:

位运算方法总结-CSDN博客

但是我发现其中涉及的内容远远不够,所以现在我们再来重新写一个博客,总结位运算算法

相比于之前的内容,我找到了一张更全的位运算计算总结,这里给大家参考一下!!!

除了这些我们再来补充一些其余的:

判断两数符号是否相同:

int x,y;
bool f=((x^y)<0);

判断一个数是否是2 的幂次:

int x;
bool f=(x^(x-1))==0;


计算较小值/计算较大值:(useless)

int x,y;
//小值:
int min=y^((x^y)&-(x<y));
int max=x^((x^y)&-(x<y));


得到右数第一个1和后面的 0 构成的数:

int x;
int ret=x&(-x);
//或者
int ret2=x-(x&(x-1));

计算一个数的二进制有几个 1:

int x,count;
while(x)
{
    x=&(x-1);
    count++;
}

交换两个数:

int a,b;
a^=b;
b^=a;
a^=b;

位运算还经常被用于状态压缩时的集合枚举。
比如现在有 n件物品,编号从1到n,我们可以用一个n位二进制数来表示每个物品取或不取的状态,二进制数从右往左数第 k位的 01 状态表示编号为k的物品取了还是没有取(1 表示取了,0 表示没有取)。
在枚举集合进行运算的过程当中,我们经常遇到要枚举当前集合的子集或超集的情况

下面我们给出子集和超集的概念:

子集:对于两个集合A与B,如果集合A的任何一个元素都是集合B的元素,我们就说集合A包含于集合B,或集合B包含集合A,也说集合A是集合B的子集

超集:如果一个集合S2中的每一个元素都在集合S1中,且集合S1中可能包含S2中没有的元素,则集合S1就是S2的一个超集

下面我们来学习如何枚举一个二进制所有的子集:

int n;//n指的是二进制位数
for (int i = 1; i < (1 << n); i++)
{
	for (int j = i; j; j = (j - 1) & i)
	{
		//枚举所有子集
	}
}

枚举一个二进制所有的超集:

int n;//n指的是二进制位数
for (int i = 1; i < (1 << n); i++)
{
	for (int j = i; j < (1 << n); j = (j + 1) | i)
	{
		//枚举所有超集
	}
}


时间复杂度都是O(3的n次方)

感谢大家的支持!!!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiaofi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值