LeetCode 371.两整数之和
不使用运算符 + 和-,计算两整数a 、b之和。
题目考察的是基本的布尔代数知识。
二进制表示时:
0 + 0 = 00
1 + 0 = 01
0 + 1 = 01
1 + 1 = 10
所以一个二进制整数,在表示相加的过程中,如果没有进位的话其实尽是异或操作,如果单纯考虑进位的话其实是与操作然后和位操作。
采用递归写代码
1 |
|
整理一下位运算
符号 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
I | 或 | 两个位都是 0 时,结果才为 0 |
^ | 异或 | 两个位相同时为 0,相异为 1 |
~ | 取反 | 0 变 1,1 变 0 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补 0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补 0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补 0 (逻辑右移) |
注意以下几点:
- 在这6种操作符,只有 ~ 取反是单目操作符,其它5种都是双目操作符。
- 位操作只能用于整形数据,对 float 和 double 类型进行位操作会被编译器报错。
- 位操作符的运算优先级比较低,因为尽量使用括号来确保运算顺序,否则很可能会得到莫明其妙的结果。比如要得到像 1,3,5,9 这些 2^i+1 的数字。写成 int a = 1 << i + 1; 是不对的,程序会先执行 i + 1,再执行左移操作。应该写成 int a = (1 << i) + 1;
- 另外位操作还有一些复合操作符,如 &=、|=、 ^=、<<=、>>=
使用:
1. 判断奇偶性
2. 交换两数
3. 变换符号:变换符号只需要取反操作后加 1 即可
4. 求绝对值
1
2
int j = a >> 31;
System.out.println((a ^ j) - j);
5. 位操作与空间压缩
位操作技巧
1 | // 1. 获得int型最大值 |
<< : 左移运算符,num << 1,相当于num乘以2
>> : 右移运算符,num >> 1,相当于num除以2
>>> : 无符号右移,忽略符号位,空位都以0补齐