被除數÷除數=商+餘數
需要注意的問題:
- int 的範圍是
[-2^31,2^31-1],也就是【-2147483648,2147483647】
,如果-2147483648/-1結果會超出int 範圍。 - 除法,乘法和mod都不能使用,那可以使用加減,移位。
- 只需保留商即可
- 保證數據在int範圍。
電腦做二進制除法的時候,是讓被除數連續減去幾次除數(減去n倍除數),直到差小於除數時爲止,這樣減去的次數就是商,剩下的差就是餘數。
可以借鑑這個思想。
解法一:每次自增除數
當然被除數減去除數也可以。
如 10/3,除數自增,10在【3+3+3,3+3+3+3】範圍裏面。
如果被除數取得很大,除數取得很小,那麼會很慢。(二者同號情況下)
下面代碼有個錯誤,就是int會溢出。
class Solution {
public int divide(int dividend, int divisor) {
if(dividend==0) return 0;
if(dividend==Integer.MIN_VALUE&&divisor==-1){
return Integer.MAX_VALUE;
}
int ans=1;//商
int f=-1;//兩個數是否異號
if(dividend<0&&divisor<0||dividend>0&&divisor>0) f=1;
if(f==-1){
//異號的話,全部變爲正數。
dividend=Math.abs(dividend);
divisor=Math.abs(divisor);
}
int temp=0;
int d=divisor;
while(true){
if(divisor==dividend) return f==-1?-ans:ans;
if(divisor>dividend&&temp<dividend){
//找到結果
ans--;
return f==-1?-ans:ans;
}
temp=divisor;
divisor+=d;
ans++;
}
}
}
解法二
注意Math.abs()
源碼
public static int abs(int a) {
return (a < 0) ? -a : a;
}
****************************************
public static long abs(long a) {
return (a < 0) ? -a : a;
}
所以參數需要強轉一下。
用dividend/2^n
來減少減法的次數。(加法和減法的原理一樣)
當dividend/2^n>=divisor
的時候,說明dividend-divisor*2^n>=0
,
於是可以用dividend-=divisor*2^n
來簡化。
這樣每次最多循環32次。
class Solution {
public int divide(int dividend, int divisor) {
if(dividend==0) return 0;
if(dividend==Integer.MIN_VALUE&&divisor==-1) return Integer.MAX_VALUE;
int ans=0;
int f=-1;
if(dividend<0&&divisor<0||dividend>0&&divisor>0) f=1;
long c_divisor=Math.abs((long)divisor);
long c_dividend=Math.abs((long)dividend);
for(int i=31;i>=0;i--){
if((c_dividend>>i)>=c_divisor){
ans+=(1<<i);
c_dividend=c_dividend-(c_divisor<<i);
}
}
return f*ans;
}
}
那這個算法的正確性如何呢?
解法二和解法三一個是>>,一個是<<。
道理一樣。
解法三
大致思路:每次讓dividend=dividend-n*divisor(且每次的n取值儘可能大)
此題限制,我們可以用位移運算,此時的n一定是2的倍數。那麼和解法二差不多。
所以首先讓diviosor>dividend,然後開始計算。
class Solution {
public int divide(int dividend, int divisor) {
if(dividend==0) return 0;
if(dividend==Integer.MIN_VALUE&&divisor==-1) return Integer.MAX_VALUE;
int ans=0;
int f=-1;
if(dividend<0&&divisor<0||dividend>0&&divisor>0) f=1;
long c_divisor=Math.abs((long)divisor);
long c_dividend=Math.abs((long)dividend);
int count=0;
while(c_divisor<=c_dividend){
//使c_divisor大於c_dividend
count++;
c_divisor=c_divisor<<1;//這裏如果不使用log就會溢出。
}
while(count>0){
count--;
c_divisor=c_divisor>>1;
if(c_divisor<=c_dividend){
ans+=1<<count;
c_dividend-=c_divisor;
}
}
return f*ans;
}
}
當然注意題目所說的數據都是int範圍的,所以不用long
class Solution {
public int divide(int dividend, int divisor) {
if(dividend==0) return 0;
if(dividend==Integer.MIN_VALUE&&divisor==-1) return Integer.MAX_VALUE;
int ans=0;
int f=-1;
if(dividend<0&&divisor<0||dividend>0&&divisor>0) f=1;
if(dividend==Integer.MIN_VALUE) {
if (divisor < 0) {
dividend -= divisor;
ans++;
} else {
dividend += divisor;
ans++;
}
if(dividend==0) return ans*f;
}else if(divisor==Integer.MIN_VALUE) return 0;
int c_divisor=Math.abs(divisor);
int c_dividend=Math.abs(dividend);
for(int i=31;i>=0;i--){
if((c_dividend>>i)>=c_divisor){
ans+=(1<<i);
//System.out.println(ans);
c_dividend=c_dividend-(c_divisor<<i);
}
}
return f*ans;
}
}