原题目
两整数之和:
不使用运算符 + 和 - ,计算两整数 a 、b 之和。
示例 1:
输入: a = 1, b = 2
输出: 3
示例 2:
输入: a = -2, b = 3
输出: 1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-two-integers
两数相除
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/divide-two-integers
题目分析
题目一:
不使用运算符+和-,说明不能直接对两数字加减,可以用位运算
两个整数a, b; a ^ b是无进位的相加; a&b得到每一位的进位;让无进位相加的结果与进位不断的异或, 直到进位为0;
位运算中的加法
我们先来观察下位运算中的两数加法,其实来来回回就只有下面这四种:
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0(进位 1)
仔细一看,这可不就是相同位为 0,不同位为 1 的异或运算结果嘛~
异或和与运算操作
我们知道,在位运算操作中,异或的一个重要特性是无进位加法。我们来看一个例子:
a = 5 = 0101
b = 4 = 0100
a ^ b 如下:
0 1 0 1
0 1 0 0
———
0 0 0 1
a ^ b 得到了一个无进位加法结果,如果要得到 a + b 的最终值,我们还要找到进位的数,把这二者相加。在位运算中,我们可以使用与操作获得进位:
a = 5 = 0101
b = 4 = 0100
a & b 如下:
0 1 0 1
0 1 0 0
————
0 1 0 0
由计算结果可见,0100 并不是我们想要的进位,1 + 1 所获得的进位应该要放置在它的更高位,即左侧位上,因此我们还要把 0100 左移一位,才是我们所要的进位结果。
那么问题就容易了,总结一下:
a + b 的问题拆分为 (a 和 b 的无进位结果) + (a 和 b 的进位结果)
无进位加法使用异或运算计算得出
进位结果使用与运算和移位运算计算得出
循环此过程,直到进位为 0
参考链接:https://leetcode-cn.com/problems/two-sum/solution/wei-yun-suan-xiang-jie-yi-ji-zai-python-zhong-xu-y/
注:LeetCode不支持负数左移。
完整代码
题目一:
int getSum(int a, int b){
int sum=a,carry=b;
while(carry)
{
int c=sum;
sum=sum^carry;
carry=(unsigned)(c&carry)<<1;
}
return sum;
}
题目二:
int divide(int dividend, int divisor)
{
int res=0,flag=1;
if(dividend==INT_MIN&&divisor==-1||dividend==INT_MAX&&divisor==1)
return INT_MAX;
if(dividend==INT_MIN&&divisor==1||dividend==INT_MAX&&divisor==-1)
return INT_MIN;
if(dividend<0&&divisor>0||dividend>0&&divisor<0)
flag=-1;
long dividend1=fabs(dividend);
long divisor1=fabs(divisor),divisor2=divisor1;
while(dividend1>=divisor2)
{
int i=0;
while(dividend1>=divisor1)
{
dividend1-=divisor1;
divisor1=divisor1<<1;
res+=1<<i;
i++;
}
divisor1=divisor2;
}
res*=flag;
return res;
}
class Solution {
public:
int divide(int dividend, int divisor) {
if(dividend == INT_MIN && divisor == -1){//负数最小值除-1只能得到正数最大数
return INT_MAX;
}
int symbol = 1;//默认符号为正
if(dividend<0&&divisor>0||dividend>0&&divisor<0){//判断结果正负
symbol = -1;
}
long dividend1 = abs(dividend);
long divisor1 = abs(divisor);
long res = 0;
while(dividend1 >= divisor1){
long temp = divisor1;
int k = 1;
while(dividend1 >= temp<<1){//循环n次,找k=2^n个除数,使被除数无法在被除
temp = temp<<1;
k = k << 1;
}
res += k;//加入结果
dividend1 -= temp;//求剩余被除数
}
return symbol*res;
}
};
总结
了解位运算的使用