开学了。。最近一是懒了。。二是事情多。。。上了刷了一下leetcode。。
29. Divide Two Integers
Given two integers dividend
and divisor
, divide two integers without using multiplication, division and mod operator.
Return the quotient after dividing dividend
by divisor
.
The integer division should truncate toward zero.
Example 1:
Input: dividend = 10, divisor = 3
Output: 3
Example 2:
Input: dividend = 7, divisor = -3
Output: -2
Note:
- Both dividend and divisor will be 32-bit signed integers.
- The divisor will never be 0.
- Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows.
这一题我做了很久说实话一直没做出来。。。
怪我太蠢了。。我一开始的想法就是把除法拆成加法,这个没什么。。我就拆成最普通的加法。。一直减下去,这当然会超时。。
于是发现了一个很经典的做法,也算是学习了。。。
举个栗子,我们假设要求100 / 3,很明显答案是33。。如果是把除法拆成加法,我们就是100 -3 = 97,97-3 = 94 ...直到余数小于3为止,然后把减的次数记录下来得出结果。。。在本题必然会超时。。
我们可以这样做,先设置一个指数参数Pow = 1,我们先判断3 + 3 = 6 < 100,如果成立,pow + 1 = 2
然后用100-6,此时我们就减了2个3,然后剩余94,我们直接判断6 + 6 = 12 < 94 ,很明显成立,那么pow *2 就行,因为减2个6相当于减了4个3..如此循环下去,我们就找到了最大的是96,这时候pow = 32,然后100 - 96 = 4,4 >3 重置Pow = 1,重复上述过程就行了。。
这个方法的好处在于大大减少了时间复杂度,比起传统的一次一次减,这个方法是每次都用2 * n 去减。。如果我没错就是把复杂度从O(n)降到了O(log2 n),有点类似于二分。。真的很好的一个想法。。代码写得不好。。想了想还是贴上来吧。。
public int divide(int dividend,int divisor) {
if(dividend == 0 || divisor == 0) {
return 0;
}
boolean flag = true;
if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0))
flag = false;
long a = Math.abs((long)dividend);
long b = Math.abs((long)divisor);
long sum = 0;
long pow = 0;
long result = 0;
if(a < b) {
return 0;
}
while(a >= b) {
sum = b;
pow = 1;
while(sum + sum <= a) {
sum += sum;
pow += pow;
}
a -= sum;
if(flag){
result += pow;
if(result > 2147483647)
result = 2147483647;
}else{
result -= pow;
if(result < -2147483648)
result = -2147483648;
}
}
return (int)result;
}