• [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; 
        }
    }
  • 相关阅读:
    Ionic开发Hybrid App问题总结
    >>> 主页链接
    微信小程序之WebSocket
    Keepalived+LVS+nginx搭建nginx高可用集群
    centos7 dns(bind)安装配置
    samba安装配置
    redis数据备份还原
    gitlab部署
    gitlab数据迁移
    kubeadm部署一个Kubernetes集群
  • 原文地址:https://www.cnblogs.com/airwindow/p/4289573.html
Copyright © 2020-2023  润新知