位运算
一、几个基础的位运算
1、‘<<’(左移)
就是将一个数对应的二进制整体向左移且高位溢出则丢弃,末尾补零。

/>2、‘>>’(右移)
2、‘>>’(右移)
与上面的左移相反,一个数的二进制整体向右移丢弃最低位,不同的是如果原先的二进制的第一位是1,则补1,0则补0.

3、‘&’(与)、‘|’(或)、‘^’(异或)
1.与运算就是只要有0就是0,全为1才是1。
2.或运算就是有1就有1全0才为0.
3.异或运算是两者相同就为0,两者不同就为1(类似于消消乐)。
二、简单的几道位运算的题
1.获取某个数的二进制数的某一位是0还是1
void Test1() { int number;//判断的数字 int n;//判断的位数(二进制的第一位为0位) cin >> number >> n; int ret = (number >> n) & 1; cout << ret << endl; }

2.将二进制的第x位的改成1
void Test2() { int number;//修改的数字 int n;//修改的位数(二进制的第一位为0位) cin >> number >> n; //0001 0111 0001 1101 0011 //94675 //0001 1111 0001 1101 0011 //127443 int ret = (1 << n) | number; cout << ret << endl; }

3.将二进制的第x位的改成0
void Test3() { int number;//修改的数字 int n;//修改的位数(二进制的第一位为0位) cin >> number >> n; //0001 0111 0001 1101 0011 //94675 //0001 1111 0001 1101 0011 //127443 //1. //int ret = (1 << n) ^ number; //2. int ret = (~(1 << n)) & number; cout << ret << endl; cout << ret << endl; } ```
4.提取一个数最右侧的1
把一个int类型的数,提取出最右侧的1来,例如:
对应的二进制位 0000 0110,那么取出来的应该是0000 0010void Test4() { int number;//修改的数字 cin >> number; //0001 0111 0001 1101 0011 //94675 // //1110 1000 1110 0010 1101 //-94675 //0001 0111 0001 1101 0010 int ret = (number) & (-number); cout << ret << endl; }

5.删除最右侧的1
void Test5() { int number;//修改的数字 cin >> number; //0001 0111 0001 1101 0011 //94675 // //1110 1000 1110 0010 1101 //-94675 //0001 0111 0001 1101 0010 int ret = (number) & (number-1); cout << ret << endl; }

6.260. 只出现一次的数字 III
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
题目的意思很简单就是将数组中两个只出现一次的数字找出来并返回。
、
一拿到题我们的想法可能是用哈希表,但是题目中要求我们使用常量的额外空间去进行解决。
所以我们就想之前那道只出现一次数字的题是用异或解决的,所以我们就可以去想这道题是否也可以用异或的思想解决呢?
答案是:能!
相比于那题来说这题的数字是两个,所以我们就就想到是不是应该分成两组,两组同时异或,两组异或的结果就是两个答案,那要怎么分组呢?
通过观察两个数来说,从低位向高位看起的时候,总会出现一个不同的二进制位,像5和3则是第一位不同(二进制的最左边为第0位),所以这就是3和5的一个不同之处,所以我们可以将数组中分为两类,一类是第一位为0的数字,另一类是第一位为1的数字。
那么我们要怎么得到……0000010这样的数组呢?
很简单就是现将数组中所有数字异或,最后得到的就是3和5异或的结果这样就可以得到从左边开始的第一个不同的位的数据(……000110),然后就变成了提取最后一位的1的问题,只需将该数据与该数据的负数&操作就可以得到(……010)。
在分组:即可得到结果。
class Solution { public: vector<int> singleNumber(vector<int>& nums) { int sum=0; for(auto num:nums) sum^=num; if(sum==INT_MIN)//防止溢出 sum=INT_MIN; else sum=(sum)&(-sum);//目的是通过与运算将最后一位1区别出来,因为只有一位数 //该位为1 int first=0;int end=0; for(auto num:nums) { if(num&sum) first^=num; else end^=num; } return {first,end}; } }; first^=num; else end^=num; } return {first,end}; } };




被折叠的 条评论
为什么被折叠?



