LeetCode029——两数相除

我的LeetCode代码仓:https://github.com/617076674/LeetCode

原题链接:https://leetcode-cn.com/problems/divide-two-integers/description/

题目描述:

知识点:二分搜索

思路一:将除法改为多次减法运算(LeetCode中超时)

虽然这个思路在LeetCode中超时了,但这个思路还是有很多值得注意的点。

(1)为防止越界,将所有的运算数都转换成long类型的数据来进行运算。

(2)设立flag来通过运算数的正负提前标记结果的正负,之后的运算全部转换成正数的运算。

这个思路的时间复杂度是O(dividend / divisor),空间复杂度是O(1)。

JAVA代码:

public class Solution {
	
	public int divide(int dividend, int divisor) {
		if(dividend == 0) {
			return 0;
		}
        //set a flag to record the result is positive or negative
		Boolean flag = true;
		if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
			flag = false;
		}
		long tempDividend = (long)dividend;
		long tempDivisor = (long)divisor; 
		if(tempDividend < 0) {
			tempDividend = -tempDividend;
		}
		if(tempDivisor < 0) {
			tempDivisor = -tempDivisor;
		}
		long result = 0;
		while(tempDividend >= tempDivisor) {
			tempDividend -= tempDivisor;
			result++;
		}
		if(flag) {
			if(result > Integer.MAX_VALUE) {
				return Integer.MAX_VALUE;
			}else {
				return (int)result;
			}
		}else {
			if(-result < Integer.MIN_VALUE) {
				return Integer.MAX_VALUE;
			}else {
				return (int)(-result);
			}
		}
    }
}

思路二:对思路一的改进,每一次减去的数在倍增

对于思路一而言,其每次减少的数都是divisor,该数一直保持不变。我们可以想象,如果这个divisor绝对值很小,比如是1,而dividend的绝对值很大,比如是Integer.MAX_VALUE,那么就要进行Integer.MAX_VALUE次减法,这个时间复杂度是难以接受的。

题目中要求不能用乘法和除法,但我们可以对减数进行倍增操作。对于dividend,如果dividend - divisor > 0,那么我们下一次减去的数不是divisor,而是divisor + divisor,这样倍增减数的操作可以使我们的时间复杂度到达O(log(dividend / divisor))的级别。而空间复杂度依然保持O(1)的级别。

对于最乐观的情况,假设divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ n = dividend。那么我们总共只进行了n次操作,这个时间复杂度显然就是O(log(dividend / divisor))。而如果divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ n > dividend,但是divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ (n - 1) < dividend,那么我们就要以dividend - (divisor + divisor * 2 + divisor * 2 ^ 2 + divisor * 2 ^ 3 + ... + divisor * 2 ^ (n - 1))为被减数进行重复的操作,即从divisor开始减起。直至我们的被减数小于divisor为止。

而对于结果的值,我们需要根据flag还有是否越界来讨论清楚各种情况。

JAVA代码:

public class Solution {

	public int divide(int dividend, int divisor) {
		if(dividend == 0) {
			return 0;
		}
        //set a flag to record the result is positive or negative
		Boolean flag = true;
		if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
			flag = false;
		}
		long tempDividend = (long)dividend;
		long tempDivisor = (long)divisor; 
		if(tempDividend < 0) {
			tempDividend = -tempDividend;
		}
		if(tempDivisor < 0) {
			tempDivisor = -tempDivisor;
		}
		long result = 0;
		while(tempDividend >= tempDivisor) {
			long k = 1;
			long temp = tempDivisor;
			while(tempDividend >= temp) {
				tempDividend -= temp;
				result += k;
				k += k;
				temp += temp;
			}
		}
		if(flag) {
			if(result > Integer.MAX_VALUE) {
				return Integer.MAX_VALUE;
			}else {
				return (int)result;
			}
		}else {
			if(-result < Integer.MIN_VALUE) {
				return Integer.MAX_VALUE;
			}else {
				return (int)(-result);
			}
		}
	}
}

LeetCode解题报告:

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值