难度:中等
给定两个整数,被除数 dividend
和除数 divisor
。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend
除以除数 divisor
得到的商。
整数除法的结果应当截去(truncate
)其小数部分,例如:truncate(8.345) = 8
以及 truncate(-2.7335) = -2
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333..) = truncate(3) = 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333..) = -2
提示:
- 被除数和除数均为 32 位有符号整数。
- 除数不为 0。
- 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
题目解析:
分析一下题目要求,首先不能用乘除法,位运算某种程度上也是乘除法。这里应该使用加减法递归。我们可以把结果进行一个展开,如下:
dividend = divisor*2^0 + divisor*2^1 + divisor*2^2 +.......
这里有一个问题,怎么把上述表达式转换成纯加法的表达式。这里使用累加和的形式res += res,进行一个乘二的操作,直至 dividend剩余值小于res,接着递归。
参考代码:
#include "iostream"
#include "vector"
#include "string"
using namespace std;
class Solution {
public:
//该函数为本算法的灵纹
int div(int dividend, int divisor)
{
//转换好的INT_MIN,传过来可能又变成了负数,所以这里还要转换一次
long long my_dividend = abs((long long)dividend);
long long my_divisor = abs((long long)divisor);
//结束条件被除数小于除数
if (my_dividend < my_divisor) return 0;
int res = 1;
int temp_sor = my_divisor;
//进行一个累加和展开,类似于dividend = divisor*2^0 + divisor*2^1+....
while ((my_dividend - temp_sor)> temp_sor)
{
res += res;
temp_sor += temp_sor;
}
//上述步骤只是进行了一步,并且是从后往前的,所以得递归前一个
return res + div(my_dividend - temp_sor, my_divisor);
}
int divide(int dividend, int divisor) {
//考虑被除数为0的情况
if (dividend == 0) return 0;
//考虑被除数和除数相等的情况
if (dividend == divisor) return 1;
//考虑除数为正负一的情况
if (divisor == 1) return dividend;
//这边要特别考虑负一的情况,如果被除数是INT_MIN,那应该返回INT_MAX
if (divisor == -1) return (dividend == INT_MIN) ? INT_MAX : -dividend;
//考虑符号问题
bool sign = !((dividend > 0) ^ (divisor > 0)) ;
//统一转换为正数进行处理,因为INT_MIN转换为正数可能会溢出,所以得使用longlong类型
//long类型是不能保证64位的,有可能是32位
long long my_dividend = abs((long long)dividend);
long long my_divisor = abs((long long)divisor);
//使用递归求出除数
int res = div(my_dividend, my_divisor);
//判断符号
if (sign == false) res = -res;
return res;
}
};
int main()
{
Solution solution;
cout << solution.divide(INT_MIN, 2) << endl;
system("pause");
return 0;
}
参考代码:
class Solution {
public:
int my_divide(long long dividend, long long divisor)
{
int res = 0;
long long temp_divisor = abs(divisor);
long long temp_dividend = abs(dividend);
if (temp_dividend >= temp_divisor)
{
res = 1;
while ((temp_dividend - temp_divisor) > temp_divisor)
{
res += res;
temp_divisor += temp_divisor;
}
return res + my_divide(abs(temp_dividend - temp_divisor), abs(divisor));
}
else
{
return 0;
}
}
int divide(int dividend, int divisor) {
if (dividend == 0)
return 0;
if (divisor == 1) return dividend;
if (divisor == -1) return (dividend == INT_MIN) ? INT_MAX : -dividend;
bool signal = false;//默认为正号
if (dividend < 0 && divisor > 0 || dividend > 0 && divisor < 0)
signal = true;
long long res = abs(my_divide(abs(dividend), abs(divisor)));
if (signal)
return -res;
else
return res;
}
};