當我第一次看到這個題目時候我我心想不就是兩數相除嘛,這麼簡單的題目爲何要放到 Medium 中,事實證實我當時的想法Too young,Too simple,Too naive 以致於被打臉n次,能夠直接查看最後答案,中間個人思路自白能夠忽略。java
給兩個數字,除數和被除數,在不使用乘、除、取模的方法作除法,返回兩數之商api
備註:
1.除數和被除數都是32位有符號整數
2.除數不爲0
3.假設咱們正在處理一個只能在32位有符號整數範圍內存儲整數的環境[−231, 231 − 1],對於這個問題若是結果溢出了,則能夠返回231 − 1ide
public class Solution { /**總體思路是用減法**/ public int divide(int dividend, int divisor) { // 符號相同用減法 if(dividend==Integer.MIN_VALUE&&divisor==-1) { return Integer.MAX_VALUE; } if ((dividend ^ divisor) >= 0) { return getQuotientUsesSubtraction(dividend, divisor); } else { int absDividend = Math.abs(dividend); int absDivisor = Math.abs(divisor); if (absDividend < 0) { absDivisor = -absDivisor; } else if (absDivisor < 0) { absDividend = -absDividend; } return 0 - getQuotientUsesSubtraction(absDividend, absDivisor); } } /** * 使用減法獲取兩個數的商 除數dividend,被除數divisor * 條件:dividend*divisor >0 且divisor>0 */ private int getQuotientUsesSubtraction(int dividend, int divisor) { int quotient = 0; if (dividend >= 0) while (dividend >= divisor) { quotient++; dividend = dividend - divisor; } else { while (dividend <= divisor) { quotient++; dividend = dividend - divisor; } } return quotient; } }
用的是 junit5,若是是4或者3的胖友本身修改下測試
import org.junit.Assert; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("不用乘除取模運算計算除數") public class TestSolution { @Test @DisplayName("MIN_VALUE狀況和1") void e1() { int out = Integer.MIN_VALUE; Solution s = new Solution(); Assert.assertEquals(out, s.divide(Integer.MIN_VALUE, 1)); } @Test @DisplayName("MIN_VALUE狀況和-1") void e9() { int out = Integer.MAX_VALUE; Solution s = new Solution(); Assert.assertEquals(out, s.divide(Integer.MIN_VALUE, -1)); } @Test @DisplayName("除數是0狀況") void e2() { int out = 0; Solution s = new Solution(); Assert.assertEquals(out, s.divide(0, 1)); } @Test @DisplayName("符號相反") void e3() { int out = -1; Solution s = new Solution(); Assert.assertEquals(out, s.divide(1, -1)); } @Test @DisplayName("符號相同") void e4() { int out = 1; Solution s = new Solution(); Assert.assertEquals(out, s.divide(-1, -1)); } @Test @DisplayName("除數MIN_VALUE和被除數MAX_VALUE") void e5() { int out = -1; Solution s = new Solution(); Assert.assertEquals(out, s.divide(Integer.MIN_VALUE, Integer.MAX_VALUE)); } @Test @DisplayName("除數MAX_VALUE和被除數MIN_VALUE") void e6() { int out = 0; Solution s = new Solution(); Assert.assertEquals(out, s.divide(Integer.MAX_VALUE, Integer.MIN_VALUE)); } @Test @DisplayName("冒煙測試10,3") void e7() { int out = 3; Solution s = new Solution(); Assert.assertEquals(out, s.divide(10, 3)); } @Test @DisplayName("冒煙測試7,-3") void e8() { int out = -2; Solution s = new Solution(); Assert.assertEquals(out, s.divide(7, -3)); } }
看到上面的運行時間內心涼了大半啊!,看來還有更好的方法,有時間的話寫一下最優解的思路
,此處立下flag,我要寫 Part 2靠你們spa
既然乘、除、取模都用不了就用減法吧。兩數取商用減法的角度思考🤔就是,被除數能夠減幾個除數。由於題目取值範圍是包含負值的因此要區分符號,相同符號則返回正數,符號相反則返回負值code
代碼:ip
class Solution { public int divide(int dividend, int divisor) { int absDividend= Math.abs(dividend); int absDivisor= Math.abs(divisor); int quotient =0; while(absDividend>absDivisor){ quotient++; absDividend=absDividend-absDivisor; } if((dividend^divisor)>= 0){ return quotient; }else{ return 0-quotient; } } }
while(absDividend>absDivisor)
改成while(absDividend>=absDivisor)
代碼內存
class Solution { public int divide(int dividend, int divisor) { // 符號相同用減法 if ((dividend ^ divisor) >= 0) { return getQuotientUsesSubtraction(dividend, divisor); } else { int absDividend = Math.abs(dividend); int absDivisor = Math.abs(divisor); if (absDividend < 0) { absDivisor = -absDivisor; } else if (absDivisor < 0) { absDividend = -absDividend; } return 0 - getQuotientUsesSubtraction(absDividend, absDivisor); } } private int getQuotientUsesSubtraction(int dividend, int divisor) { int quotient = 0; if (dividend >= 0) while (dividend >= divisor) { quotient++; dividend = dividend - divisor; } else { while (dividend <= divisor) { quotient++; dividend = dividend - divisor; } } return quotient; } }