LeetCode刷題——29. Divide Two Integers(Part 1靠本身)

當我第一次看到這個題目時候我我心想不就是兩數相除嘛,這麼簡單的題目爲何要放到 Medium 中,事實證實我當時的想法Too young,Too simple,Too naive 以致於被打臉n次,能夠直接查看最後答案,中間個人思路自白能夠忽略。java

clipboard.png

題目大意

給兩個數字,除數和被除數,在不使用乘、除、取模的方法作除法,返回兩數之商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));
    }

}

時間和空間複雜度

clipboard.png

clipboard.png

看到上面的運行時間內心涼了大半啊!,看來還有更好的方法,有時間的話寫一下最優解的思路
,此處立下flag,我要寫 Part 2靠你們spa


初級解題思路(🤷‍♀️此處開始爲我折騰過程不重要,能夠忽略)

既然乘、除、取模都用不了就用減法吧。兩數取商用減法的角度思考🤔就是,被除數能夠減幾個除數。由於題目取值範圍是包含負值的因此要區分符號,相同符號則返回正數,符號相反則返回負值code

第一次嘗試(失敗🙄)

  • 思路:
  1. 取兩個數的絕對值
  2. 當被除數大於除數時,計算相減次數,小於時則直接返回0
  3. 當兩數相同符號則返回相減次數,符號相反則返回相減次數負值
  • 代碼: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;
            }
        }
    }
  • 結果
    自測的兩個冒煙測試用例經過,可是用例[1,1]沒用經過

第二次嘗試(失敗😨)

  • 分析失敗緣由
    循環的時候沒有考慮相等的狀況
  • 修改方式
    while(absDividend>absDivisor)改成while(absDividend>=absDivisor)
  • 修改後[1,1]用例經過,可是未經過用例[-2147483648,-1]

第三次嘗試(失敗😰)

  • 分析失敗緣由
    沒有考慮負數的最大值的絕對值溢出了
  • 修改方式
    修改思路
    1.符號相同的時候直接獲取相減次數
    2.符號不一樣的時候,取兩數的絕對值
    3.判斷兩數的絕對值是否大於0,(小於0的狀況是取值爲−231
    4.大於0時,返回相減次數的絕對值
    5.小於0時,將大於0的數取反數再計算相減次數,返回相減次數的反數
  • 代碼內存

    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;
    
        }
    }
  • 結果
    未經過用例[-2147483648,-1],可是能夠處理除數或被除數爲-2147483648的其餘用例能夠處理

第四次嘗試(成功✌️)

  • 分析失敗緣由
    沒有考慮負數最大值除以-1致使溢出
  • 修改方式 直接將這個用例視爲特殊狀況處理之,直接返回整值最大
相關文章
相關標籤/搜索