算法:位运算
1.常见位运算总结
1.基础位运算
&: 有0就是0。
|:有一就是一
^:相同为0,相异为1。
2.给定一个数n,确定它的二进制表示中的第x位是 0 还是 1
(n >> x) & 1
3.将一个数n的二进制表示的第x位修改成1
n = n | (1 << x)
4.将一个数n的二进制表示的第x位修改成0
n = n & (~(1 << x))
5.位图的思想
哈希表中里面开32个空间
6.提取一个数(n)二进制表示中最右侧的1
n & (-n) 。将最右侧的1,左边的区域全部变成相反的。
7.去除一个数(n)二进制表示中最右侧的1
n & (n - 1)。
8.位运算的优先级和多,所以建议能加括号就加括号
9.异或运算的运算律
a ^ 0 = a. a ^ a = 0. a^b^c = a^(b^c)。
2.判断字符是否唯一
面试题 01.01. 判定字符是否唯一 - 力扣(LeetCode)
思路一:哈希表
思路二:位图+鸽巢原理。
class Solution {
public:bool isUnique(string astr) {if(astr.size() > 26)return false;int bitmap = 0;//位图for(auto e : astr){int i = e - 'a';if(((bitmap >> i) & 1 ) == 1)//插入前如果第i位等于1,那么就存在了不唯一的字符return false;bitmap |= (1 << i);//插入位图,将第i位置为1}return true;}
};
3.丢失的数字
268. 丢失的数字 - 力扣(LeetCode)
解法一:哈希表。
解法二:高斯求和。
解法三:位运算:异或。
class Solution
{
public:int missingNumber(vector<int>& nums) {int n = nums.size();int ret = 0;for(auto e : nums){ret ^= e;} for(int i = 0; i <= n; i++){ret ^= i;}return ret;}
};
4.两正数之和
371. 两整数之和 - 力扣(LeetCode)
思路:位运算 : 异或(算出无进位相加)+ & 算出进位的值。
class Solution
{
public:int getSum(int a, int b) {while(b != 0){int x = a ^ b;//算出无进位相加int crray = (a & b) << 1;a = x;b = crray;}return a;}
};
5.只出现一次的数字2
137. 只出现一次的数字 II - 力扣(LeetCode)
思路:位运算,因为有三次相同的数字,将每一次出现的数字的当前位加起来%3,就是只出现一次的当前为的值。
class Solution
{
public:int singleNumber(vector<int>& nums){int ret = 0;for(int i = 0; i < 32; i++){int sum = 0;for(auto e : nums){if(((e >> i) & 1) == 1)sum++;}sum %= 3;ret |= sum << i;}return ret;}
};
6.消失的两个数字
面试题 17.19. 消失的两个数字 - 力扣(LeetCode)
这道题相当于 丢失的数字 + 只出现一次的数字3
思路:位运算
1.将所以数异或在一起,(1 ~ N和数组nums)
2.找到tmp中比特位上位1的哪一位
3.根据x位的不同,划分成两类再异或。
class Solution
{
public:vector<int> missingTwo(vector<int>& nums) {int n = nums.size();int sum = 0;for(auto e : nums){sum ^= e;}for(int i = 1; i <= n + 2; i++){sum ^= i;}int x = 0;for(int i = 0; i < 32; i++){if(((sum >> i) & 1) == 1)x = i;}int type1 = 0,type2 = 0;for(auto e : nums){if(((e >> x) & 1) == 1)type1 ^= e;elsetype2 ^= e;}for(int i = 1; i <= n + 2; i++){if(((i >> x) & 1) == 1)type1 ^= i;elsetype2 ^= i;}return {type1,type2};}
};