算法原理
常见的位运算总结
1.基础位运算
<<左移
>>右移
~按位取反
&按位与 有0就是0
|按位或 有1就是1
^异或 相同位0,相异为1/无进位相加
2.给定一个数n,确定他的二进制表示中的第x位是0还是1

3.将一个数n的二进制位表示的第x位修改为1

4.将一个数n的二进制位表示的第x位修改为0

5.位图的思想(本质就是哈希表)
我们可以用int[]来模拟一个哈希表,但当数据过大的时候,这样并不适用,我们就尝试使用位图的思想,一个int有32个比特位,每个位置可以存储0或1的信息,这样能存储的数据就大幅度增加了
(上述2,3,4都是应用了位图的思想)
6.提取一个数(n)二进制表示中最右侧的1
n&-n

7.干掉一个数(n)二进制表示中最右侧的1
n&n-1

8.运算符的优先级
能加括号就加括号
9.异或运算的运算律
1.a^0=a;
2.a^a=0;
3.a^b^c=a(b^c)
题目解析
1.判断字符是否唯一
https://leetcode.cn/problems/is-unique-lcci/
题目描述
实现一个算法,确定一个字符串s的所有字符是否全部不同
算法原理
解法一:哈希表(o(n)的时间复杂度和空间复杂度)
解法二:位图

优化点:鸽巢原理(如果len>26,一定有重复的字符出现)
代码实现
public boolean isUnique(String astr) {
if(astr.length()>26){
return false;
}
int bitMap=0;
for(int i=0;i<astr.length();i++){
int x=astr.charAt(i)-'a';
if(((bitMap>>x)&1)==1) return false;
bitMap |=1<<x;
}
return true;
}
2.消失的数
https://leetcode.cn/problems/missing-number/description/
题目描述
给定一个包含[0,n]中n个数的数组nums,找出[0,n]这个范围内没有出现在数组中的那个数
算法原理
1.哈希表
将数组中的元素加到哈希表中,然后遍历哈希表找出那个不存在的元素(用数组模拟实现哈希表,遍历数组,存在将数组对应的值改为1)
2.高斯求和
ret=(0+nums.length)/2-sum[nums];
3.位运算(异或运算的运算律)
a^a=0 a^0=a;
让0与数组中每一位异或,再与0异或到数组的 长度,这样出现的数被异或了2次,结果不受影响,而未出现的数字被异或了一次,结果就会是缺失的数字
代码实现
public int missingNumber(int[] nums) {
int ret=0;
for(int num:nums){
ret^=num;
}
for(int i=0;i<=nums.length;i++){
ret^=i;
}
return ret;
}
3.两整数之和
https://leetcode.cn/problems/sum-of-two-integers/
题目描述
给你两个整数a和b,不使用运算符+和-,计算并返回两整数之和
算法原理
位运算(异或运算--无进位相加)

代码实现
class Solution {
public int getSum(int a, int b) {
while(b!=0){
int x=a^b;
b=(a&b)<<1;
a=x;
}
return a;
}
}
4.只出现一次的数字
https://leetcode.cn/problems/single-number-ii/
题目描述
给定一个数组nums,除某个元素仅出现一次外,其余元素恰好出现了三次,请找出并返回哪个只出现了一次的元素
算法原理
使用位图的思想,依次修改ret每个比特位的值,每次修改的时候统计所有数字第i位的和,如果最后结果%3的结果为1,ret|=(1<<i)

代码实现
class Solution {
public int singleNumber(int[] nums) {
int ret=0;
for(int i=0;i<32;i++){
int sum=0;
for(int x:nums){
if(((x>>i)&1)==1){
sum++;
}
}
sum=sum%3;
if(sum==1){
ret|=(1<<i);
}
}
return ret;
}
}
5.消失的两个数
https://leetcode.cn/problems/missing-two-lcci/
题目描述
给定一个数组,包含从1到n的所有整数,但是缺少了两个数字,在O(N)时间内在O(1)空间里找到这两个数字
算法原理
这道题类似于丢失的数字+只出现一次的数字
解法:位运算
1.将所有的数异或在一起,tmp
2.找到tmp中比特位为1的那一位
3.根据x位的不同,划分两类进行异或

代码实现
java
class Solution {
public int[] missingTwo(int[] nums) {
// 1.先把所有的数字异或在一起
int tmp=0;
for(int x:nums){
tmp^=x;
}
for(int i=1;i<=nums.length+2;i++){
tmp^=i;
}
// 2.找出a b比特位不同的哪一位
int diff=0;
while(true){
if(((tmp>>diff)&1)==1){
break;
}else{
diff++;
}
}
// 3.将所有的数按照diff位不同,分成两类异或
int[] ret=new int[2];
for(int x:nums){
if(((x>>diff)&1)==1) ret[1]^=x;
else{
ret[0]^=x;
}
}
for(int i=1;i<=nums.length+2;i++){
if(((i>>diff)&1)==1)
ret[1]^=i;
else{
ret[0]^=i;
}
}
return ret;
}
}