LeetCode刷题day029 (Jieky)

LeetCode第29题

/*
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:
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.
*/
import java.util.*;
import java.lang.*;
public class DivideTwoIntegers{
    public static void main(String[] args){
        DivideTwoIntegers dti = new DivideTwoIntegers();
        int result = dti.divide(2147483647,1);
        System.out.println(result);
    }

	// 直接使用负数进行运算,避免处理绝对值溢出问题的处理
    public int divide(int dividend, int divisor) {
        int binary = 0b10000000000000000000000000000000;
        // 除数为0,直接返回0
        if (dividend == 0) return 0;
        // 除数、被除数相等。直接返回1
        if (dividend == divisor) return 1;
        // 除数小于被除数,直接返回0
        int temp_dividend = (dividend&binary) == binary ? dividend : ~dividend + 1;
        int temp_divisor = (divisor&binary) == binary ? divisor : ~divisor + 1;
        if (temp_dividend > temp_divisor) return 0;

        // 判断两个数是否同号
        int flag = (dividend&binary) == (divisor&binary) ? 0 : 1;

		// 除数为1则直接返回被除数,要判断溢出的问题
        if (temp_divisor == -1) return flag == 0 ? (temp_dividend == Integer.MIN_VALUE? Integer.MAX_VALUE:~temp_dividend+1) : temp_dividend;

        // 不用除法求商:https://zhuanlan.zhihu.com/p/108566985
        int base = temp_divisor;
		// 这里就不用处理-2147483648的问题
        int left = temp_dividend;
        int result = 0;
        int count = 1;
        while (left <= temp_divisor){
            // base >= (Integer.MIN_VALUE >> 1)防止base溢出
			// >>表示除2,<<表示乘2
            while ((base >= (Integer.MIN_VALUE >> 1)) && ((base << 1)  >= left)) {
                // 2 4 8 16,每次增加的数正好是上次的1倍
                count = count << 1;
                base = base << 1;
                System.out.println(base);
                if (base >= 0) break;
            }
            if (base >= 0) break;
            // 将已经获得的倍数累加起来
            result -= count;
            // 将已经减去的数更新剩下的left
            left -= base;

            // 重置base和count,为下一次计数做准备
            base = temp_divisor;
            count = 1;
        }

        // result是负数,因此异号不变号,但是要处理溢出问题
        return flag == 0 ? (result == Integer.MIN_VALUE? Integer.MAX_VALUE:~result+1) : result;
    }

    public int divide03(int dividend, int divisor) {
        int binary = 0b10000000000000000000000000000000;
        int maxInt = 0b01111111111111111111111111111111;
        // 除数为0,直接返回0
        if (dividend == 0) return 0;
        // 除数、被除数相等。直接返回1
        if (dividend == divisor) return 1;
        // 除数小于被除数,直接返回0
         int temp_dividend = (dividend&binary) == binary ? dividend : ~dividend + 1;
         int temp_divisor = (divisor&binary) == binary ? divisor : ~divisor + 1;
         if (temp_dividend > temp_divisor) return 0;

        // 判断两个数是否同号
        int flag = (dividend&binary) == (divisor&binary) ? 0 : 1;

        // -2147483648 的绝对值还是 -2147483648
        int abs_dividend = Math.abs(dividend);
        int abs_divisor = Math.abs(divisor);

        if (abs_divisor == 1){
            // 两个数同号,且dividend为最大负数,则发生溢出
            if(dividend == binary && flag==0) return maxInt;
            // 若两个数异号,则对abs_dividend进行符号变更,所有位取反加一(正负数都适用)
            return flag == 1 ? ~abs_dividend+1 : abs_dividend;
        }

        // 不用除法求商:https://zhuanlan.zhihu.com/p/108566985
        int base = abs_divisor;
        // 处理abs_dividend为-2147483648情况,有-2147483648 - 2 = 2147483646
        int left = abs_dividend - base;
        int result = 1;
        int count = 1;
        while (left >= abs_divisor){
            // base <= (maxInt >> 1)防止base溢出
            while ((base <= (maxInt >> 1)) && ((base << 1)  <= left)) {
                // 2 4 8 16,每次增加的数正好是上次的1倍
                count = count << 1;
                base = base << 1;
            }
            // 将已经获得的倍数累加起来
            result += count;
            // 将已经减去的数更新剩下的left
            left -= base;

            // 重置base和count,为下一次计数做准备
            base = abs_divisor;
            count = 1;
        }

        // 根据是否溢出返回相应的值
        return flag == 1 ? ~result+1 : result;
    }

    public int divide02(int dividend, int divisor) {
        if (dividend == 0) return 0;
        if (divisor == 0) return 100000;

        int binary = 0b10000000000000000000000000000000;
        int maxInt = 0b01111111111111111111111111111111;

        // 判断两个数是否同号
        int flag = (dividend&binary) == (divisor&binary) ? 0 : 1;

        int abs_dividend = Math.abs(dividend);
        int abs_divisor = Math.abs(divisor);

        if (abs_divisor == 1){
            // 两个数同号,且dividend为最大负数,则发生溢出
            if(dividend == binary && flag==0) return maxInt;
            // 若两个数异号,则对abs_dividend进行符号变更,所有位取反加一(正负数都适用)
            return flag == 1 ? ~abs_dividend+1 : abs_dividend;
        }

        // -2147483648 - 2 = 2147483646,虽然abs_dividend为-2147483648,但是不影响结果
        int count = 0;
        boolean overflow = false;
        int temp = abs_dividend - abs_divisor;
        // 3 - (-2147483648) 溢出得-2147483645,不进入循环,得到正确的结果
        // -2147483648 - 3 溢出得2147483645,结果与2147483648 - 3等价,得到正确的结果
        while(abs_dividend - abs_divisor >= 0) {
            count++;
            abs_dividend -= abs_divisor;
        }

        // 根据是否溢出返回相应的值
        return flag == 1 ? ~count+1 : count;
    }


    public int divide01(int dividend, int divisor) {
        if (dividend == 0) return 0;
        if (divisor == 0) return 100000;

        int binary = 0b10000000000000000000000000000000;
        int maxInt = 0b01111111111111111111111111111111;

        // 判断两个数是否同号
        int flag = (dividend&binary) == (divisor&binary) ? 0 : 1;

        int abs_dividend = Math.abs(dividend);
        int abs_divisor = Math.abs(divisor);

        if (abs_divisor == 1){
            // 两个数同号,dividend为最大负数且divisor为1,则发生溢出
            if(dividend == binary && flag==0) return maxInt;
            // 两个数异号,则对abs_dividend进行符号变更,所有位取反加一(正负数都适用)
            return flag == 1 ? ~abs_dividend+1 : abs_dividend;
        }

        // 前面已经处理溢出问题,接下来的运算不会溢出
        int count = 0;
        boolean overflow = false;
        while(abs_dividend - abs_divisor >= 0) {
            // 标记是否发生溢出
            if (count == maxInt){
                overflow = true;
                break;
            }
            count++;
            abs_dividend -= abs_divisor;
        }

        // 根据是否溢出返回相应的值
        return overflow == false ? (flag == 1 ? ~count+1 : count) : maxInt;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值