刷刷笔试题--[位运算编程题]
来源:互联网 发布:国密算法实现 编辑:程序博客网 时间:2024/05/17 08:58
解析:
最正规的做法:
异或运算的性质:任何一个数字异或它自己都等于0 。
也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,
因为那些出现两次的数字全部在异或中抵消掉了。
如果能够把原数组分为两个子数组。
在每个子数组中,包含一个只出现一次的数字,而其它数字都出现两次。
如果能够这样拆分原数组,按照前面的办法就是分别求出这两个只出现一次的数字了。
我们还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。
因为其它数字都出现了两次,在异或中全部抵消掉了。
由于这两个数字肯定不一样,那么这个异或结果肯定不为0 ,也就是说在这个结果数字的二进制表示中至少就有一位为1 。
我们在结果数字中找到第一个为1 的位的位置,记为第N 位。
现在我们以第N 位是不是1 为标准把原数组中的数字分成两个子数组,
第一个子数组中每个数字的第N 位都为1 ,而第二个子数组的每个数字的第N 位都为0 。
现在我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其它数字都出现了两次。
[2*8比2<<3快]
2<<3是左移,是2进制的运算
2*8,还要做很多的运算。
一般,我们都说2进制运算最快。
["<<"这个是左移位运算符],"2<<3"表示2左移3位
2的二进制是00000000 00000000 00000000 00000010
2左移3位,高位的移出,低位的用0填充。
结果:00000000 00000000 00000000 00010000
这个数是16
[m<<n]: 等于m*(2的n次方)
5可以表示为:00000101(最高位表示符号,0位正,1为负)
[>>右移]后为00000010
^ 按位异或。[相同为0不同为1]
比如二进制 1001 ^ 1100 = 0101
0^0=0,1^1=0 ,1^0 = 1,0^1=1。
& 按位与
int a = 10;
int b =2;
a&b=2 ,按位与,算术运算..1010&0010 = 0010
a&&b = true 并且,逻辑运算.
/* * 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 */public class xorProblem {public void FindNumsAppearOnce(int[] array,int num1[],int num2[]){if(array==null||array.length==0)return;int temp=0;for(int i=0;i<array.length;i++){temp^=array[i];//异或数组中所有的数字}//index1是指那两个数异或时第一个出现1的位置int index1=findFirstBitOne(temp);//遍历数组,按那一位是1还是0把数组分成两个数组for(int i=0;i<array.length;i++){if(isBit(array[i],index1))num1[0]^=array[i];elsenum2[0]^=array[i];}}//寻找一个数的二进制表示中,第一个1出现的位置,从右到左开始找public int findFirstBitOne(int num){int index=0;//num中的二进制位不停地和1按位与,index标记位数//不要超过int的bit数就好,int四个字节,每个字节8bit,所以8*4,最好直接写成32while(((num&1)==0)&&(index)<8*4){num=num>>1;//对num进行右移,把最右边比较完的数挤出去++index;}return index;}//给出之前找到的index,判断其他数,这一位是不是1public boolean isBit(int num,int index){num=num>>index;return (num&1)==1;}}
2.不用加减乘除做加法
解析:
一看到这种题就知道要用位运算来解决
let's have a good look
首先看十进制是如何做的:5+7=12
第一步:相加各位的值,不算进位,得到2
第二步:计算进位值,得到10,如果这一步的进位值为0,那么在这一步终止,得到最终结果
第三步:重复上两步,相加的值变成了2+10,得到12,没有进位,进位值为0,循环终止,否则一直相加,直到进位值为0
同样,用这三步来计算二进制相加:5->101,7->111,
第一步:相加各位的值,不算进位,二进制每位相加就相当于做异或操作,101^111=010[相同为0不同为1]
第二步:计算进位值,相当于二进制各位数与,再向左移一位,(101&111)<<1 = 101<<1=1010
第三步:重复上两步:010^1010=1100,(010&1010)<<1= 0,进位值为0,跳出循环,1100为最终结果
public class Solution { public int Add(int num1,int num2) { while(num2!=0){ int temp=num1^num2; num2=(num1&num2)<<1; num1=temp; } return num1; }}
- 刷刷笔试题--[位运算编程题]
- 刷刷笔试题--[链表类编程]
- 刷刷笔试题~(4)编程
- 刷刷笔试题~~[字符串类编程]
- 刷刷笔试题~~[算数类编程]
- 刷刷笔试题~~[二叉树编程]
- 刷刷笔试题~~[递归类编程]
- 刷刷笔试题~~[递归]
- 刷刷笔试题~~[概率]
- 刷刷笔试题~~[数组]
- 刷刷笔试题~~[sql]
- 刷刷笔试题~~ [Java]
- 刷刷笔试题~~[矩阵]
- 刷刷笔试题~~[操作系统!!!]
- 刷刷笔试题~(1)
- 刷刷笔试题~(2)
- 刷刷笔试题~~(3)
- 刷刷笔试题~~~[动态规划!!!!]
- 微信公众平台二次开发JAVA
- 2009 3
- 深入理解Java微服务架构Dubbo系列—— 第一回 结缘
- Ajax提交数据给后台
- 算法导论(2)
- 刷刷笔试题--[位运算编程题]
- JZOJ4769 【GDOI2017模拟9.9】graph CDQ分治+用按秩合并维护带撤销的并查集(BZOJ 4025)
- 电路与Multisim基础 电流源示例
- Direct3D顶点坐标变换
- Java的集合框架
- TCP、UDP、IP 协议分析
- Java-NowCoder-字符串分隔
- 电路与Multisim基础 电容遇到交流+直流电路时,容抗与隔直通交的特性
- 只要四步即可将win10本本变成无线热点