版权声明:由于一些问题,理论类博客放到了blogger上,希望各位看官莅临指教https://efanbh.blogspot.com/;本文为博主原创文章,转载请注明本文来源 https://blog.csdn.net/wyf826459/article/details/82014970
目录
题目描述:
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.
算法实现
首先为了方便,将题目改造成,正整数除以正整数,这个过程不在叙述
一、纯减法
最简单的方法就是写一个循环,用被除数不断的减去减数,直到被减数小于减数,但是会超时
二、官网方法
具体思路为,我减去的不再是减数,而是减去减数的倍数,可是又不能使用乘法,那么减数的倍数怎么实现呢?用移位的方式;
//官网实际答案
class Solution {
public:
int divide(int dividend, int divisor) {
long long a = abs((double)dividend);
long long b = abs((double)divisor);
long long ret = 0;
while (a >= b) {
long long c = b;
for (int i = 0; a >= c; ++i, c <<= 1) {
//std::cout<<"1-1 a="<<a<<", c="<<c<<" ,i="<<i<<" ,ret="<<ret<<std::endl;
a -= c;
ret += 1 << i;
//std::cout<<"1-2 a="<<a<<", c="<<c<<" ,i="<<i<<" ,ret="<<ret<<std::endl;
}
}
return ((dividend^divisor)>>31) ? (int)(-ret) : (int)(ret);
}
看两个例子
//49/7
1-1 a=49, c=7 ,i=0 ,ret=0
1-2 a=42, c=7 ,i=0 ,ret=1
1-1 a=42, c=14 ,i=1 ,ret=1
1-2 a=28, c=14 ,i=1 ,ret=3
1-1 a=28, c=28 ,i=2 ,ret=3
1-2 a=0, c=28 ,i=2 ,ret=7
49 / 7 = 7
// 64/7
1-1 a=64, c=7 ,i=0 ,ret=0
1-2 a=57, c=7 ,i=0 ,ret=1
1-1 a=57, c=14 ,i=1 ,ret=1
1-2 a=43, c=14 ,i=1 ,ret=3
1-1 a=43, c=28 ,i=2 ,ret=3
1-2 a=15, c=28 ,i=2 ,ret=7
1-1 a=15, c=7 ,i=0 ,ret=7
1-2 a=8, c=7 ,i=0 ,ret=8
1-1 a=8, c=7 ,i=0 ,ret=8
1-2 a=1, c=7 ,i=0 ,ret=9
64 / 7 = 9
三、个人在官网方法启发下写的算法
与前一种方法不同,我所寻找的是能够小于被减数的,减数能够左移的最大位数,使被减数减去这一移位完成的数值,不断重复,直到减数小于被减数。具体采用递归的方式实现
class Solution {
public:
long long divide_plus(long long a, long long b){
if(a < b) return 0;
long long i = 1;
long long c = b;
while(c <= a)
{
c = c << 1;
i = i << 1;
}
return (i >> 1) + divide_plus(a - (c >> 1), b);
}
int divide(int dividend, int divisor) {
bool flag;
if(dividend == 0) return 0;
if((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0))flag = true;
if((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0))flag = false;
long long a = abs((long long)(dividend));
long long b = abs((long long)(divisor));
long long res = flag==true ? divide_plus(a,b) : -divide_plus(a,b);
if(res > INT_MAX) return INT_MAX;
if(res < INT_MIN) return INT_MIN;
return int(res);
}
};
attention:
- 无论是官网解法abs((double)dividend)中的强制转换为double型,还是我自己实现的算法中转化成long long型都是防止INT_MIN的绝对值溢出
- 不知道为什么不管是数值超出INT_MAX还是数值小于INT_MIN,强制转换为int后的结果都是INT_MIN。因此是通过判断大小来将其数值范围限定在INT范围内的,而不是通过强制转换来实现。