29. Divide Two Integers[M]兩數相除

題目


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:python

  • 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: \([−2^{31}, 2^{31} − 1]\). For the purpose of this problem, assume that your function returns \(2^{31} − 1\) when the division result overflows.

思路


位移運算

(1)題意

要求咱們實現兩個整數的除法的操做,而且不能使用乘、除、模運算。兩個整數都是32位整數,假設被除數是M,除數是m。ide

(2)特殊狀況:溢出

除法的溢出有兩種狀況:this

  • 除數m爲0(雖然題目已經假設m不爲0,可是本身仍是要考慮到);
  • 被除數M是最小數INT_MIN,除數m爲1。
(3)符號處理:異或

在除法操做中,同號爲正,異號爲負,這有點相似於異或操做:值相同異或爲0,值不一樣異或爲1。因而咱們利用一個標誌位來記錄符號。再對被除數M和除數m取絕對值,這裏注意,取絕對值時,因爲32位整數範圍爲\([−2^{31}, 2^{31} − 1]\),在對除數m取絕對值時,必須將類型設置long或者long long型,不然當除數m爲最小值時,取絕對值後會溢出。spa

(4)除法實現:逐漸逼近

題目要求不能利用乘、除、取模來實現除法。首先看除法的意義,假設36 / 9 = 4,將它換成36 - 9 - 9 - 9 - 9 = 0,這個時候發現能夠用減法來逐漸逼近:36減去4次9等於0,而36除以9也是4(實際上減去減去4次9就是9 *4了)。另外一種狀況是:若是不能整除怎麼辦?假設36 / 8 ,它的商是4。換成36 - 8 - 8 - 8 - 8 =4 < 8,這個時候發現不夠減了,就不減了,商正好是4。因而咱們能夠用一個循環來實現除法操做:看被除數M減去了幾回除數m,將減去屢次m後的值與m比較(小於等於m時),獲得商。
可是,這種每次只減一個除數m的循環太慢了,程序很容易超時。咱們但願每次能夠多減幾個m,好比2的倍數次。爲何是2的倍數次?由於兩次能夠用位運算實現。
m << 0 至關於m * 1
m << 1 至關於m * 2
m << 2 至關於m * 4
因而咱們須要利用一個變量i來記錄位運算的移動次數,以及一個臨時變量來記錄除數m的左移操做以後的結果(m << i)。
此時的循環變爲M 與 m << i比較。.net

Tips


位操做(C++)

(1)位運算

|| | | |
| :---: | :---: | :---: |
| & | 邏輯與 | 0 & 1 =0 |
| | | 邏輯或 | 0 | 1 = 1 |
| ^ | 異或 | 0 ^ 1 = 1 |
| ~ | 逐位求反 | ~1 = 0 |
| << | 左移 | 8 << 1 = 16 |
| >> | 右移 | 8 >> 1 = 4 |
| <<= | 左移後賦值 | a <<=1 即 a= a<<1 |
| >>= | 右移後賦值 | a >>=1 即 a= a>>1 |code

(2)用途
  • 由上面能夠看出a<<b就是將a乘以2的b次方(\(a * 2^b\))。一般認爲<<1要比2更快,由於位移操做是更底層的一些操做。所以程序中2的操做盡可能用>>1代替,以提升程序效率。此外,能夠用1<<來定義一些常量。
  • 相似地,a>>b就是將a除以2的b次方取整(\(\frac{a}{2^b}\))。一般用>>1來代替/2的操做,好比二分查找,堆的插入操做等。想辦法用>>代替除法可使程序的效率大大提升。

C++

class Solution {
public:
    int divide(int dividend, int divisor) {
        
        //首先考慮特殊狀況:溢出
        if(divisor == 0 || (dividend == INT_MIN && divisor == -1))
            return INT_MAX;
        
        //異或操做處理正負號
        bool isNeg = ((dividend < 0) ^ (divisor < 0));
        
        long m = abs((long)dividend); //被除數
        long n = abs((long)divisor); //除數,這裏必須是long或者long,不然取絕對值後會溢出。
        long result = 0; //商
        long count = 0; //記錄次數
        
        while(m >= n){
            
            long tempVal = n; //記錄左移操做的中間結果
            count = 0;
            
            //每次乘以2,直到不能減爲止
            while(m >= (tempVal << 1)){
                count ++;
                tempVal <<= 1;
            }
            
            m -= tempVal;
            result += 1 << count;
        }
        
        return isNeg ? -result : result;     
    }
};

Python

參考

[1] https://blog.csdn.net/a1351937368/article/details/77746574/blog

相關文章
相關標籤/搜索