做题关键点--位操作符

x |(x+1)去掉从右开始的第一个0

a^a=0,异或遵循交换律,即只要存在偶数个a,这部分结果为0.

a^0=a  与0异或为本身

寻找奇数

寻找奇数_牛客题霸_牛客网

不用加减乘除做加法_牛客题霸_牛客网

不用加减乘除做加法

二进制进行加法运算时与十进制的思路是一致的,第一部分是不进位部分相加,第二部分是拿到进位的大小,然后将两部分相加。

例如:计算15+07时,第一部分为12,第二部分为10,两部分相加为22.

由于二进制只有0、1两种数字,可以不使用加法,而是通过位运算实现逻辑上的相加。

例如:我们实现5+7,  5:  0101        7:  0111

第一部分:不考虑进位时,相加得到 0010,拆开来看,两个0还是0,一个0一个1是1,两个1是0,即相异时为1,因此可以使用按位异或操作符^     得到0010也就是2

第二部分:考虑进位的部分,相加得到0101,然后<<1得到1010,只有两个都为1时才为1,然后左移进行进位,因此可使用按位与操作符&,   得到1010也就是10

经过上面两步,我们将5+7转换为了2+10,此时我们发现还需要继续进行加法操作,于是我们重复上述两个部分的操作。

2: 0010      10:  1010

第一部分: 1000即8

第二部分: 0100即4

转换为8+4,继续转换

8:  1000    4:  0100

第一部分:1100即12

第二部分:0000即0

当第二部分需要进位的部分为0时,我们的加法过程就结束了,第一部分就是相加后的最终结果。

int Add(int num1, int num2 ) {
    while(num2!=0)
    {
        int tmp=num1^num2;
        num2=(num2&num1)<<1;
        num1=tmp;
    }    
    return num1;
}

   num1^num2求的是第一部分,(num1&num2)<<1求的是第二部分,第二部分为0时结束。这里我用了tmp来接收第一部分的值,防止影响第二部分值的计算,也可以创建两个变量,使得逻辑更加清晰。

int main()
{
	int num1 = 0;
	int num2 = 0;
	while (num2 != 0)
	{
		int tmp1=num1^ num2;
		int tmp2 = (num1 & num2) << 1;
		num1 = tmp1;
		num2 = tmp2;
	}
}

力扣

整数转换(力扣)

寻找单身狗

题目名称:
找单身狗
题目内容:
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
例如:有一组数组 1 2 3 4 5 1 2 3 4 6,里面的5和6只出现了一次,想办法找到这两个单身狗。

由前面的题目可知,当一个数出现偶数次时,按位异或的结果为0,如果这组数字只有一个出现奇数次的话,我们直接将所有数字按位异或即可找到单身狗。

但此题有两条单身狗,我们可以将它们分为两组,每组一条单身狗,然后其他数据都是出现偶数次的。

那么如何分类呢?分类的条件是找矛盾,或是找到两个数据的不同点。

5的二进制表示为0101    6的二进制表示为0110   将5^6可以得到 0011,这两个1就是二者的区别,因此我们可以通过最低位是否为1来区分5和6,同时也可以将其它成对数据进行分组。

void search_single_dog(int arr[], int size, int single_dog[])
{
	//先将所有数按位异或,找到区分点
	int i = 0;
	int ret = 0;
	for (i = 0; i < size; i++)
	{
		ret ^= arr[i];
	}
	//得到0011或其它值,但总有一位为1   
	//ret=3
	int pos = 0;
	for (i = 0; i < 32; i++)
	{
		if (((ret >> i) & 1) == 1)//1为0001,将ret的每一位与1&,得到1则最后一位是1
		{                         
			pos = i;//用pos标记右移几位开始不同
			break;
		}
	}
	//pos=0
	for (i = 0; i < size; i++)
	{
		//pos位置为0的放到dog[0],pos位置为1的放到dog[1]中
		if (((arr[i] >> pos) & 1 )== 0)//这里必须注意括号 ==前面的那个必须加,==优先级高于&,否则if一直不会执行,&1==0,先计算1==0,得到0,if语句永远不执行
		{
			single_dog[1] ^= arr[i];
		}
		else
		{
			single_dog[0] ^= arr[i];
		}
	}

}
int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
	int size = sizeof(arr) / sizeof(arr[0]);
	int single_dog[2] = { 0 };
	//创建dog数组用来存放两个单身狗(因为只能返回一个数据,除非传址调用)
	search_single_dog(arr, size, single_dog);
	printf("%d %d", single_dog[0], single_dog[1]);
}

目录

寻找奇数

不用加减乘除做加法

整数转换(力扣)

寻找单身狗


  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值