位运算骚操作
异或操作
异或运算性质
1)异或运算就是无进位相加
2)异或运算满足交换律、结合律,也就是同一批数字,不管异或顺序是什么,最终的结果都是一个
3)0^n=n,n^n=0
4)整体异或和如果是x,整体中某个部分的异或和如果是y,那么剩下部分的异或和是x^y
骚操作
- 交换两个数
void exchange(int &a, int &b)
{
if(a == b) return; //防止&a,&b指向同一个地址;那样结果会错误。
a ^= b ^= a ^= b;
}
- 不用任何判断语句和比较操作,返回两个数的最大值
// 非负数返回1 负数返回0
int sign(int n)
{
return !(unsigned int)n >> 31;
}
void getmax(int a, int b)
{
// c可能溢出
int c = a - b;
// a的符号
int sa = sign(a);
// b的符号
int sb = sign(b);
// c的符号
int sc = sign(c);
// 判断A和B,符号是不是不一样,不一样就返回1, 一样就返回0
int diffAB = sa ^ sb;
// 判断A和B,符号是不是一样,一样就返回1, 不一样就返回0
int sameAB = !diffAB;
int returnA = diffAB * sa + sameAB * sc;
int returnB = !returnA;
return a * returnA + b * returnB
}
- 找到缺失的数字
https://leetcode.cn/problems/missing-number/
class Solution {
public:
int missingNumber(vector<int>& nums) {
int all = 0, miss = 0;
int size = nums.size();
for(int i = 0; i < size; i ++ )
{
all ^= i;
miss ^= nums[i];
}
all ^= size;
return all ^ miss;
}
};
- 提取出二进制里最右侧的1
// Brian Kernighan算法
int right_one(int x)
{
return x & (-x); // 返回int,但是32位里只有1个位置是1,且为最右边那个
}
位运算的骚操作
- 判断一个整数是不是2的幂
// Brian Kernighan算法
bool isPowerOfTwo(int n)
{
return n > 0 && n == (n & -n);
}
- 判断一个数是不是3的幂
// 如果一个数字是3的某次幂,那么这个数一定只含有3这个质数因子
// 1162261467是int型范围内,最大的3的幂,它是3的19次方
// 这个1162261467只含有3这个质数因子,如果n也是只含有3这个质数因子,那么
// 1162261467 % n == 0
// 反之如果1162261467 % n != 0 说明n一定含有其他因子
bool isPowerOfThree(int n)
{
return n > 0 && (1162261467 % n == 0);
}
bool isPowerOfThree2(int n)
{
while(n && (n % 3 == 0)) n /= 3;
return n == 1;
}
- 抹去最右边的1
n = n & (n - 1);
- 逆序二进制的状态
https://leetcode.cn/problems/reverse-bits/
// 位运算分治
class Solution {
private:
const uint32_t M1 = 0x55555555; // 01010101010101010101010101010101
const uint32_t M2 = 0x33333333; // 00110011001100110011001100110011
const uint32_t M4 = 0x0f0f0f0f; // 00001111000011110000111100001111
const uint32_t M8 = 0x00ff00ff; // 00000000111111110000000011111111
public:
uint32_t reverseBits(uint32_t n) {
n = n >> 1 & M1 | (n & M1) << 1;
n = n >> 2 & M2 | (n & M2) << 2;
n = n >> 4 & M4 | (n & M4) << 4;
n = n >> 8 & M8 | (n & M8) << 8;
return n >> 16 | n << 16;
}
};
位运算实现加减乘除
加
int add(int a, int b)
{
int sumtmp = a ^ b;
int carry = (a & b) << 1;
while(carry)
{
int temp = sumtmp;
sumtmp = temp ^ carry;
carry = (tmep & carry) << 1;
}
return sumtmp;
}
减
int neg(int n) // 取反
{
return add(~n, 1);
}
int minus(int a, int b) // a - b
{
return add(a, neg(b));
}
乘
int multiply(int a, int b)
{
int ans = 0;
unsigned int c = (unsigned int)b;
while(b != 0)
{
if((b & 1) != 0)
{
ans = add(ans, a);
}
a <<= 1;
c >>= 1;
}
return ans;
}
除
int div(int a, int b)
{
int x = a < 0 ? meg(a) : a;
int y = b < 0 ? neg(b) : b;
int ans = 0;
for(int i = 30; i >= 0; i = minus(i, 1))
{
if((x >> i) >= y)
{
ans |= (1 << i);
x = minus(x, y << i);
}
}
return ((a < 0) ^ (b < 0)) ? neg(ans) : ans;
}
标签:return,运算,int,异或,ans,操作,uint32
From: https://www.cnblogs.com/hnu-hua/p/18179471