java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 |
---|
文章目录
- 位运算
位运算
解题思路:时间复杂度O( l o g 2 m a x − i n t log_2{max-int} log2max−int),空间复杂度O( 1 1 1) |
---|
- 我们不能使用加减运算符。那么就只能学习硬件底层的加法器的逻辑来处理了(计算机组成原理中加法器的知识)
- 首先想要实现一位加法器,必须知道如何处理进位信息,例如1+1 = 进位1和本位0
- 也就是说,整个加法器都是由两个操作来处理,无进位加法结果,和进位后结果
- 无进位加法结果实现方法:a异或b。因为我们要实现本位1+0 = 0+1 = 1和0+0 = 1+1 = 0.
注意,这里加法是抛去进位信息的。例如1+1 =
1
0,其中1
是进位,而0是本位,我们这里只要本位信息
- 进位结果实现方法:(a & b) << 1. 因为我们要实现进位1+0 = 0+1 = 0和0+0 = 0,和1+1 = 1
1+1 = 1的原因是 1+1 = 10.也就是逢二进一,所以进位为1.
不容易理解的是进位结果为什么是(a & b) << 1
- 假设a = 0111,b = 0101.此时a&b = 0101,左移一位为1010
- 我们发现右移后的结果,里面的1正好是进位后的1需要去的地方
- 因为a+b = 0
1
11
+ 01
01
,其中标红的位置两个1相加必然会产生进位- 往哪里进位?如果允许2的出现的话,结果会是这样a+b = 0
2
12
- 但是很遗憾,不允许2的出现,所以他俩得向前进位1,也就是0
2
12
=0+1
01+1
0.也就是2需要逢二进一,进位到它们的高位- 因此a & b只能获取哪些地方是加出
2
的,这些2需要向高位进1。例如a&b = 01
01
正好对应a+b = 02
12
中需要进位的2
的位置- 因此我们需要左移一位,获取0
2
12
=0+1
01+1
0中0+1
和1+1
的进1的位置
- 例如a = 1,b = 2. 二进制分别为a = 0001,b = 0010
- 此时不考虑进位,相加结果为a^b = 0011,我们发现压根也不会产生进位信息
- 例如a = 2,b = 3,二进制分别为a = 0010,b = 0011
- 此时a ^ b = 0001,也就是不进位加法结果
- 此时获取需要进位的位置(相加为2的位置),a & b = 0010,其中1的位置,正好是a+b后二进制为按位相加 = 2的位置,这些位置需要进位1
- 因此通过左移操作,获取需要进位的1进位到哪里,(a&b)<<1 = 0100
- 此时将本位结果x = a^b = 0001和进位相加结果y = (a&b)<<1 = 0100,不进位相加x ^ y得到x = 0101 = 5.
- 继续获取进位信息(x&y)<<1 = 0000.发现没有需要进位的了,则加法完成。
代码 |
---|
class Solution {
public int getSum(int a, int b) {
//a保存本位加法信息(无进位加法),b保存进位信息
while (b != 0) {//当没有进位信息后,表示加法完成
int carry = (a & b) << 1;//获取a+b的进位信息
a = a ^ b;//获取a+b的本位信息
b = carry;//a+b的无进位加法完成,保存到a中,剩下处理进位信息即可,让b保存进位信息
//直到b的进位全部加完,不需要进位为止,此时就只需要无进位加法即可获得最终加法结果(因为没有进位可言)
}
return a;//返回
}
}