力扣第29題 中等難度 兩數相除
本來想著直接用減法的,後來發現會有溢位的情況。
因為int限制的範圍是[-2147483648,2147483647]
當我用減法來模擬除法時(首先確定結果有沒有負號,然後把兩個數都取絕對值,然後被除數不斷減去除數,直到比除數小為止),會有溢位的現象,因為一旦對-2147483648取絕對值,那麼它的絕對值還是它本身。因為int是有符號整數,把10…000(‘1’+31個0)取絕對值變成10…000(1+31個0)
注:
假設int為四位有符號整數,則-6變為6的過程:
1110→0110
-8變為8的過程:
1000→1000
於是把減法變成加法,被除數和除數都變成加法做處理,就可以避免被除數的-2147483648的情況,不用取絕對值,只需要處理極個別的特殊情況。
於是程式碼如下:
public static int divide(int dividend, int divisor) {
if(dividend==0)
return 0;
boolean minusSign = false;
//由題可知,被除數和除數以及結果均為32位有符號整數,因此存在特殊情況,使得結果溢位
//特殊情況 -2147483648/-1時,最後一次while迴圈時2147483647+1=2147483648(溢位了,系統會把他當做-2147483648),溢位時應返回2147483647
if(dividend==-2147483648&&divisor==-1)
return 2147483647;
if(dividend==-2147483648&&divisor==1)
return -2147483648;
if ((dividend > 0 && divisor > 0)) {
dividend = (-1) * dividend;
divisor = (-1) * divisor;
} else if (dividend > 0 && divisor < 0) {
minusSign = true;
dividend = (-1) * dividend;
} else if (dividend < 0 && divisor > 0) {
minusSign = true;
divisor = (-1) * divisor;
}
int res = 0;
while (dividend <= divisor) {
if(res==2147483647)
return 2147483647;
res++;
dividend -= divisor;
}
if (minusSign)
res = res * (-1);
return res;
}
提交程式碼以後,測試用例全部通過,但是時間超出限制了。看來是時間複雜度太高了。不解,故看答案思路。
答案思路:
每次讓被除數翻倍 比如13>=3 首先計數為1,然後13>=6,計數為2,13>=12,計數為4,13<24,計數不更新
看了答案思路以後自己寫的程式碼:
public static int divide(int dividend, int divisor) {
if (dividend == -2147483648 && divisor == -1)
return 2147483647;
if (dividend == -2147483648 && divisor == 1)
return -2147483648;
if (dividend == 0)
return 0;
if (dividend == divisor)
return 1;
boolean minusSign = false;
if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
dividend = dividend < 0 ? dividend : (-1) * dividend;
divisor = divisor < 0 ? divisor : (-1) * divisor;
minusSign = true;
}
int sum = 1;
int k = divisor;
if (dividend > 0 && divisor > 0) {
//兩個數都大於0
if (dividend < divisor)
return 0;
if (divisor << 1 < 0)
return 1;
divisor = divisor << 1;
boolean b = false;
while (dividend >= divisor) {
sum = sum << 1;
if (divisor << 1 < 0) {//防止放大一倍以後變成負數
b = true;
break;
}
divisor = divisor << 1;
}
if (sum > 1) {
divisor = divisor >> 1;
if (b) {
b = false;
divisor = divisor << 1;
}
divisor += k;
if (divisor < 0)
return sum;
while (dividend >= divisor) {
sum += 1;
divisor += k;
if (divisor < 0)
break;
}
}
} else {
//兩個數都小於0
//eg.-35和-5,-35<=-5,計數為1,然後-35<=-10,計數為2,-35<=-20,計數為4,
// -35>-40,計數不更新,然後從-20開始一個一個加-5
if (dividend > divisor)
return 0;
if (divisor << 1 >= 0)
return minusSign?-1:1;
divisor = divisor << 1;
boolean b = false;
while (dividend <= divisor) {
sum = sum << 1;
if (divisor << 1 >= 0) {//防止放大一倍以後變成正數
b = true;
break;
}
divisor = divisor << 1;
}
if (sum > 1) {
divisor = divisor >> 1;
if (b) {
b = false;
divisor = divisor << 1;
}
divisor += k;
if (divisor >= 0)
return minusSign?(-1) * sum:sum;
while (dividend <= divisor) {
sum += 1;
divisor += k;
if (divisor >= 0)
break;
}
}
}
if (minusSign)
return sum * (-1);
return sum;
}
相關文章
- JAVA-LeetCode中等29兩數相除JavaLeetCode
- 29.兩數相除
- LeetCode 29——兩數相除LeetCode
- 力扣第39題 組合總和 中等難度 卡了一天沒做出來力扣
- 力扣題解1-兩數之和力扣
- 力扣題解2-兩數相加力扣
- 力扣之兩數之和力扣
- 力扣1052. 愛生氣的書店老闆-C語言實現-中等難度力扣C語言
- python LeetCode 兩數相除PythonLeetCode
- Leetcode力扣1 兩數之和(Python版)LeetCode力扣Python
- 力扣題之迴文數力扣
- 【10月打卡~Leetcode每日一題】18. 四數之和(難度:中等)LeetCode每日一題
- 第 178 場力扣周賽 第二題力扣
- 演算法--力扣2. 兩數相加演算法力扣
- 力扣1438. 絕對差不超過限制的最長連續子陣列-C語言實現-中等難度力扣陣列C語言
- 力扣演算法經典第一題——兩數之和(Java兩種方式實現)力扣演算法Java
- 力扣題解力扣
- 力扣 204. 計數質數(每日一題)力扣每日一題
- 力扣.1 兩數之和 N 種解法 two-sum力扣
- 力扣演算法題:尋找兩個正序陣列的中位數力扣演算法陣列
- 力扣-697. 陣列的度力扣陣列
- 20201125:力扣第216場周賽(下)力扣
- 20201124:力扣第216場周賽(上)力扣
- 力扣之兩個陣列的交集力扣陣列
- 力扣 - 劍指 Offer 29. 順時針列印矩陣力扣矩陣
- 【一天一大 lee】四數相加 II (難度:中等) - Day20201127
- 【1月打卡~Leetcode每日一題】86. 分隔連結串列(難度:中等)LeetCode每日一題
- 力扣-349. 兩個陣列的交集力扣陣列
- 難度2:素數距離問題
- 力扣刷題——3096.得到更多分數的最少關卡數目力扣
- LeetCode 力扣 羅馬數字轉整數LeetCode力扣
- 力扣 - 劍指 Offer 22. 連結串列中倒數第k個節點力扣
- 力扣 170. 兩數之和 III - 資料結構設計 two-sum III力扣資料結構
- 用 PHP 在 力扣 上演算法 [兩數之和]{一天一更}PHP力扣演算法
- 用 PHP 在 力扣 刷演算法 [兩數相加]{一天一更}PHP力扣演算法
- 力扣.16 最接近的三數之和力扣
- 力扣之斐波那契數列力扣
- 力扣---2020.7.30力扣