LeetCode 29. Divide Two Integers 两数相除(Java)

题目:

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, which means losing its fractional part. For example, truncate(8.345) = 8 and truncate(-2.7335) = -2.

Example 1:
Input: dividend = 10, divisor = 3
Output: 3
Explanation: 10/3 = truncate(3.33333…) = 3.

Example 2:
Input: dividend = 7, divisor = -3
Output: -2
Explanation: 7/-3 = truncate(-2.33333…) = -2.

Note:

  • 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: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows.

解答:

要求不能使用除法或者取余等操作。我们可以想到,如10/3=3,其实即为三个3。而二进制运算中的位运算"<<“和”>>",分别为将数整体进行左移和右移,如a<<1表示将a向左移动一位,即可变为原来的二倍。因此我们结合二进制相关运算进行实现。

具体思路如下:

  1. 先对运算中的特殊情况进行处理
  2. 用 sign 表示运算后的符号位,若除数与被除数符号相同,则计算结果为正数;若除数与被除数符号不同,则计算结果为负数。因此采用异或运算 ^ 进行处理
  3. m 为除数的绝对值,n 为被除数的绝对值。若 m>=n,则表示 n 至少为 m 的一倍,因此初始化 count=1。若 m >= (temp<<1),说明 m 至少为 temp 的两倍,则 temp 和 count 进行翻倍。如 37/4=9,对 count 和 temp 翻倍至 count=8,temp=32,说明 32 至少为 4 的 8 倍,此时不满足翻倍条件,m=37-4*8=5,再循环一次至 count=count+1=9,为最终结果。
  4. 计算结果与符号位相乘,返回最终结果。
class Solution {
    public int divide(int dividend, int divisor) {
        if(divisor == 0 || dividend == Integer.MIN_VALUE && divisor==-1) {
            return Integer.MAX_VALUE;
        }
        int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1 ;
        long m = Math.abs((long)dividend);
        long n = Math.abs((long)divisor);
        int res = 0;
        while(m >= n) {
            long temp = n;
            int count = 1;
            while(m >= (temp<<1)){
                temp <<= 1;
                count <<= 1;                
            }
            res += count;
            m -=temp;
        }
        return sign*res;
    }
}

此题有几点需要注意的:

  1. int的范围是-2147483648~2147483647,因此对于 dividend=-2147483648,会产生溢出,需要进行特殊处理。
  2. 符号位的确定可采用异或运算,相同为0 (false),不同为 1 (true)。如 true ^ false 为 true。
    LeetCode 29. Divide Two Integers 两数相除(Java)_第1张图片
    注意对溢出情况的处理。

你可能感兴趣的:(LeetCode)