zoukankan      html  css  js  c++  java
  • [LeetCode#29]Divide Two Integers

    The problem:

    Divide two integers without using multiplication, division and mod operator.

    If it is overflow, return MAX_INT.

    My analysis:

    The idea behind this problem is very veyr elegant, it involves important mainpulataion over the digits of a number, you must master it! And this kind of problem always involves a lot of conner cases, you should be very very careful!!
    The key idea:
    solution 1: We keep on substracting divisor from dividend, and we record the times of substraction. Once we reach a value less than divisor, we return the count. The time complexity of this solution is O(n). 
    solution 2: It also uses the idea of substraction. But it substracts in a more brave way.
    num = a_0 * 2^0  +  a_1 * 2^1 + a_2 * 2^2 + a_3 * 2^3 + a_4 * 2^4 + a_5 * 2^5
    Idea:
    2.1 We left shift divisor to reach the value just less(or equal than) dividend. 
    while (divisor <= (dividend >> 1)) { //note we stop value just bigger than (dividend >> 1), cause we would stract it. 
        divisor <<= 1;
        digit++;
    }
    2.2 Then we follow the below invariant.
    Iff dividend larger than divisor, it means we could substract divisor from dividend. And we should add the substracted parts into the return value: 
    if (dividend >= divisor ) {
        ret += (1 << digit); 
        dividend -= divisor;
    }
    Note: the digit here is used to record the current divisor's left shift. it represent (1>>digit) times of original divisor.
    Then we could test number less than divisor (with lower times of divisor), by decreasing digit by one and right shift divisor one digit. 
    digit--;
    divisor >>= 1;
    Note: digit is useds to record how many times the current divisor of the original divisor. And divisor is the actual number we opearte on. 
    while (digit >= 0) {
        if (dividend >= divisor ) {
            ret += (1 << digit);
            dividend -= divisor;
        }
        digit--;
        divisor >>= 1;
    }
    
    Some tricky skills: 
    1. the sign of two numbers' product or divide. 
    boolean is_neg = (dividend ^ divisor) >>> 31 == 1;
    ">>>" respresent we right shift the number 31 digits and fill those shifted digits with 0. 
    
    2. inorder to make the uniform comparsion when we shift digits. (and the sign only affects the result's sign, not the abs () part.) We need to use the abs value of dividend and divisor in computation. To get the abs value, we shoul consider following corner cases:
    2.1 divisor is 0, we return Integer.MAX_VALUE. 
    if (divisor == 0)
        return Integer.MAX_VALUE;
        
    2.2 dividend is Integer.MIN_VALUE(the abs() over it would result in overflow). we could substract it with divisor's abs value at first, thus we would not overflow.
    if (dividend == Integer.MIN_VALUE) {
        dividend += Math.abs(divisor);
        if (divisor == -1) //note this corner case.
            return Integer.MAX_VALUE;
        ret ++; //rember to record the substraction in the result. 
    }
    
    2.3 iff the divisor is Integer.MIN_VALUE. 
    2.3.1 iff the dividend is also Integer.MIN_VALUE, we should return 1;
    2.3.2 iff the dividend is a Integer larger than Integer.MIN_VALUE, we should return 0. 
    int ret = 0;
    if (dividend == Integer.MIN_VALUE) {
        dividend += Math.abs(divisor);
        if (divisor == -1)
            return Integer.MAX_VALUE;
        ret ++;
    }
    if (divisor == Integer.MIN_VALUE) {
        return ret;
    }
    Note the logic at here is very elegant. 

    The solution:

    public class Solution {
        public int divide(int dividend, int divisor) {
            if (divisor == 0)
                return Integer.MAX_VALUE;
            boolean is_neg = (dividend ^ divisor) >>> 31 == 1;
            int digit = 0;
            int ret = 0;
            if (dividend == Integer.MIN_VALUE) {
                dividend += Math.abs(divisor);
                if (divisor == -1)
                    return Integer.MAX_VALUE;
                ret ++;
            }
            if (divisor == Integer.MIN_VALUE) {
                return ret;
            }
            divisor = Math.abs(divisor);
            dividend = Math.abs(dividend);
            while (divisor <= (dividend >> 1)) {
                divisor <<= 1;
                digit++;
            }
            while (digit >= 0) {
                if (dividend >= divisor ) {
                    ret += (1 << digit);
                    dividend -= divisor;
                }
                digit--;
                divisor >>= 1;
            }
            return is_neg ? -1 * ret : ret; 
        }
    }
  • 相关阅读:
    C# if else 使物体在X轴循环移动
    Jmeter之csv、用户自定义变量以及Query Type分析
    jmeter实战之笔记整理
    Badboy参数化
    Jmeter之Badboy录制脚本及简化脚本http请求
    jmeter之jdbc请求
    性能测试
    接口自动化学习--testNG
    接口自动化学习--mock
    Git工具使用小结
  • 原文地址:https://www.cnblogs.com/airwindow/p/4289573.html
Copyright © 2011-2022 走看看