进阶:空间复杂度 ,时间复杂度
public class Solution { public int Add(int num1,int num2) { while (num2!=0) { int temp = num1^num2; num2 = (num1&num2)<<1; num1 = temp; } return num1; } }
首先看十进制是如何做的: 5+7=12,三步走 第一步:相加各位的值,不算进位,得到2。 第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。 第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。 同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。 第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。 第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。 继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。 部门开始招聘实习生,感兴趣的同学可以看看,可以内推 https://www.nowcoder.com/jobs/detail/307599?jobId=307599
class Solution { public: int Add(int num1, int num2) { char* a = reinterpret_cast<char*>(num1); return reinterpret_cast<long>(&(a[num2])); } };
class Solution { public: int Add(int num1, int num2) { //相加各位 + 计算进位 //十进制思想 //5+7 各位相加:2 进位:10 //2+10 12 0 //12+0 //二进制计算过程 //5+7 各位相加:101^111=010 进位:101&111=101 (<<1=1010) //2+10 各位相加:010^1010=1000 进位:010&1010=010 <<1=0100 //8+4 1000^0100=1100 1000&0100=0 //12+0 if (num2 == 0) return num1; return Add(num1^num2, (num1&num2)<<1 ); } };
class Solution { public: int Add(int num1, int num2) { int result=0; __asm__( "add %1,%2\n\t" //%1表示num2 %2表示num1,这个表示num2的值加到num1上 "mov %2,%0\n\t" //%0表示目的寄存器,把num1复制到result上 :"=r"(result) //%0,占用符号 :"r"(num2),"r"(num1) //这一行是将C代码中的数据输入到汇编的代码中 ); return result; } };
class Solution: def Add(self, num1, num2): # write code here # 异或、与(与计算考虑进位)之和 xorNum = num1 ^ num2 # 不考虑进位 andNum = (num1 & num2)<<1 # 考虑进位 while andNum!=0: # 若果没有进位的话直接输出结果 tmp1 = xorNum ^ andNum tmp2 = (xorNum & andNum)<<1 tmp1 = tmp1 & 0xFFFFFFFF # 为了避免负数过大,取前32位 xorNum = tmp1 andNum = tmp2 return xorNum if xorNum<=0x7FFFFFFF else ~(xorNum^0xFFFFFFFF)
public class Solution { public int Add(int num1,int num2) { //直到不再产生进位 while (num2!=0) {//无进位求和 int UnsignedSum=num1^num2; //求出进位 int signedSum=(num1&num2)<<1; num1=UnsignedSum; num2=signedSum;} //直到进位num2为0,说明不再产生进位,num1就是最终结果 return num1; } }
//写成递归形式 //第一个参数放无进位相加结果,第二个参数放进位位 //方法:求两个参数的和 public int Add(int num1,int num2) { if(num2==0) return num1; return Add(num1^num2,(num1&num2)<<1); }
public class Solution { public int Add(int num1,int num2) { if(num2==0) return num1; return Add(num1^num2,(num1&num2)<<1); } }
public class Solution { public int Add(int num1,int num2) { while (num2!=0) { int UnDigit = num1 ^ num2; int Digit = (num1 & num2) << 1; num1 = UnDigit; num2 = Digit; } return num1; } }2021 三刷:
public class Solution { public int Add(int num1,int num2) { while(num2!=0){ int unsinged=num1 ^ num2; int signed=(num1 & num2)<<1; num1=unsinged; num2=signed;} return num1; } }
public class Solution { public int Add(int num1,int num2) { if (num2==0) return num1; return Add(num1^num2, (num1&num2)<<1); } }
1. 先看一个例子:
看一下 3 + 4 的加法运算
3 的二进制表示: 011
4 的二进制表示: 100
3^4 (3按位异或4)的结果是: 111 => 7
上面的到的结果是就是 3 + 4 的实际结果
再看一个例子:
12 的二级制表示: 01100
19 的二进制表示: 10011
12^19 的结果是: 11111 => 31
再看一个例子:
13 的二进制表示:01101
19 的二进制表示:10011
13^19 的结果是: 11110 => 20
通过上面的三个例子不难发现: 当二进制数的每一位加法中不发生进位时,按位异或的结果就是最终的加法结果,那么我需要做的就是将所有的加法操作最终都简化成没有进位的加法操作,最终的结果就是两个数按位异或的结果。
2、怎么处理有进位的加法?
拆分
将两个数的加法拆分为 进位加法和不进位加法
看一个例子:
编号:1 2 3 4 5
------------------------
1 0 0 1 1 => 19
+ 1 1 0 1 0 => 26
--------------------------
先求只有不进位的两个位相加的值,编号为2、3、5这三位的加法不发生进位操作,需要进位的相加位数直接按照结果为0处理,得到的结果为
编号:1 2 3 4 5
------------------------
1 0 0 1 1
+ 1 1 0 1 0
------------------------
不进位: 0 1 0 0 1
进位两个位相加的值,编号为1、4这三位的加***发生进位操作,不需要进位的直接按照结果0处理,得到的结果为:
编号:1 2 3 4 5
------------------------
1 0 0 1 1
+ 1 1 0 1 0
------------------------
不进位: 0 1 0 0 1
进 位: 1 0 0 1 0 0
再将两个结果按位异或:
不进位:0 0 1 0 0 1
进 位:1 0 0 1 0 0
------------------------
1 0 1 1 0 1 => 45
由此可见可以将一个二进制加法拆分为有进位的位数相加结果 和 无进位的位数相加的结果最终按位异或
3、递归
再看一个例子
编号:1 2 3 4 5
------------------------
1 0 1 1 1 => 23
+ 1 1 0 1 1 => 27
------------------------
不进位: 0 1 1 0 0 => 12
进 位: 1 0 0 1 1 0 => 38
通过一次相加得到的结果不能完全实现化简操作,所以需要递归地进行化简操作
编号:1 2 3 4 5
------------------------
1 0 1 1 1 => 23
+ 1 1 0 1 1 => 27
------------------------
不进位: 0 0 1 1 0 0 => 12
进 位:1 0 0 1 1 0 => 38
------------------------
不进位:1 0 1 0 1 0 => 42
进 位:0 0 1 0 0 0 => 8
------------------------
不进位:1 0 0 0 1 0 => 34
进 位:0 1 0 0 0 0 => 16
------------------------
不进位:1 1 0 0 1 0 => 50
进 位:0 0 0 0 0 0 => 0
以上实例通过递归的方式可以得到最终的结果
二、位运算实现
通过以上几个实例我们明白了如何通过二进制的几个步骤来实现任意整数的加法操作,现在我们需要把这件事情用位运算进行表示。
位运算表示不进位加法:
不进位加法其实就是一个异或操作
位运算表示进位加法: