我的LeetCode代码仓:https://github.com/617076674/LeetCode
原题链接:https://leetcode-cn.com/problems/divide-two-integers/description/
题目描述:
知识点:二分搜索
思路一:将除法改为多次减法运算(LeetCode中超时)
虽然这个思路在LeetCode中超时了,但这个思路还是有很多值得注意的点。
(1)为防止越界,将所有的运算数都转换成long类型的数据来进行运算。
(2)设立flag来通过运算数的正负提前标记结果的正负,之后的运算全部转换成正数的运算。
这个思路的时间复杂度是O(dividend / divisor),空间复杂度是O(1)。
JAVA代码:
public class Solution {
public int divide(int dividend, int divisor) {
if(dividend == 0) {
return 0;
}
//set a flag to record the result is positive or negative
Boolean flag = true;
if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
flag = false;
}
long tempDividend = (long)dividend;
long tempDivisor = (long)divisor;
if(tempDividend < 0) {
tempDividend = -tempDividend;
}
if(tempDivisor < 0) {
tempDivisor = -tempDivisor;
}
long result = 0;
while(tempDividend >= tempDivisor) {
tempDividend -= tempDivisor;
result++;
}
if(flag) {
if(result > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}else {
return (int)result;
}
}else {
if(-result < Integer.MIN_VALUE) {
return Integer.MAX_VALUE;
}else {
return (int)(-result);
}
}
}
}
思路二:对思路一的改进,每一次减去的数在倍增
对于思路一而言,其每次减少的数都是divisor,该数一直保持不变。我们可以想象,如果这个divisor绝对值很小,比如是1,而dividend的绝对值很大,比如是Integer.MAX_VALUE,那么就要进行Integer.MAX_VALUE次减法,这个时间复杂度是难以接受的。
题目中要求不能用乘法和除法,但我们可以对减数进行倍增操作。对于dividend,如果dividend - divisor > 0,那么我们下一次减去的数不是divisor,而是divisor + divisor,这样倍增减数的操作可以使我们的时间复杂度到达O(log(dividend / divisor))的级别。而空间复杂度依然保持O(1)的级别。
对于最乐观的情况,假设divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ n = dividend。那么我们总共只进行了n次操作,这个时间复杂度显然就是O(log(dividend / divisor))。而如果divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ n > dividend,但是divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ (n - 1) < dividend,那么我们就要以dividend - (divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ (n - 1))为被减数进行重复的操作,即从divisor开始减起。直至我们的被减数小于divisor为止。
而对于结果的值,我们需要根据flag还有是否越界来讨论清楚各种情况。
JAVA代码:
public class Solution {
public int divide(int dividend, int divisor) {
if(dividend == 0) {
return 0;
}
//set a flag to record the result is positive or negative
Boolean flag = true;
if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
flag = false;
}
long tempDividend = (long)dividend;
long tempDivisor = (long)divisor;
if(tempDividend < 0) {
tempDividend = -tempDividend;
}
if(tempDivisor < 0) {
tempDivisor = -tempDivisor;
}
long result = 0;
while(tempDividend >= tempDivisor) {
long k = 1;
long temp = tempDivisor;
while(tempDividend >= temp) {
tempDividend -= temp;
result += k;
k += k;
temp += temp;
}
}
if(flag) {
if(result > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}else {
return (int)result;
}
}else {
if(-result < Integer.MIN_VALUE) {
return Integer.MAX_VALUE;
}else {
return (int)(-result);
}
}
}
}
LeetCode解题报告: