LeetCode-----第二十九题-----两数相除

两数相除

难度:中等

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

返回被除数 dividend 除以除数 divisor 得到的商。

整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2

 

示例 1:

输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333..) = truncate(3) = 3

示例 2:

输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333..) = -2

 

提示:

  • 被除数和除数均为 32 位有符号整数。
  • 除数不为 0。
  • 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231,  231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。

 

题目解析:

       分析一下题目要求,首先不能用乘除法,位运算某种程度上也是乘除法。这里应该使用加减法递归。我们可以把结果进行一个展开,如下:

        dividend = divisor*2^0 + divisor*2^1 + divisor*2^2 +.......

这里有一个问题,怎么把上述表达式转换成纯加法的表达式。这里使用累加和的形式res += res,进行一个乘二的操作,直至 dividend剩余值小于res,接着递归。

 

参考代码:

#include "iostream"
#include "vector"
#include "string"
using namespace std;

class Solution {
public:
    //该函数为本算法的灵纹
	int div(int dividend, int divisor)
	{
        //转换好的INT_MIN,传过来可能又变成了负数,所以这里还要转换一次
		long long my_dividend = abs((long long)dividend);
		long long my_divisor = abs((long long)divisor);
        //结束条件被除数小于除数
		if (my_dividend < my_divisor) return 0;
		int res = 1;
		int temp_sor = my_divisor;
        //进行一个累加和展开,类似于dividend = divisor*2^0 + divisor*2^1+....
		while ((my_dividend - temp_sor)> temp_sor)
		{
			res += res;
			temp_sor += temp_sor;
		}
        //上述步骤只是进行了一步,并且是从后往前的,所以得递归前一个
		return res + div(my_dividend - temp_sor, my_divisor);
	}

	int divide(int dividend, int divisor) {
        //考虑被除数为0的情况
		if (dividend == 0) return 0;
        //考虑被除数和除数相等的情况
		if (dividend == divisor) return 1;
        //考虑除数为正负一的情况
		if (divisor == 1) return dividend;
        //这边要特别考虑负一的情况,如果被除数是INT_MIN,那应该返回INT_MAX 
		if (divisor == -1) return (dividend == INT_MIN) ? INT_MAX : -dividend;

        //考虑符号问题
		bool sign = !((dividend > 0) ^ (divisor > 0)) ;
        //统一转换为正数进行处理,因为INT_MIN转换为正数可能会溢出,所以得使用longlong类型
        //long类型是不能保证64位的,有可能是32位
		long long my_dividend = abs((long long)dividend);
		long long my_divisor = abs((long long)divisor);
		
        //使用递归求出除数
		int res = div(my_dividend, my_divisor);
        //判断符号
		if (sign == false) res = -res;

		return res;
	}
};

int main()
{
	Solution solution;

	cout << solution.divide(INT_MIN, 2) << endl;
	
	system("pause");
	return 0;
}

 

参考代码:

class Solution {
public:
	int my_divide(long long dividend, long long divisor)
	{
		int res = 0;
		long long temp_divisor = abs(divisor);
		long long temp_dividend = abs(dividend);
		if (temp_dividend >= temp_divisor)
		{
			res = 1;
			while ((temp_dividend - temp_divisor) > temp_divisor)
			{
				res += res;
				temp_divisor += temp_divisor;
			}
			return res + my_divide(abs(temp_dividend - temp_divisor), abs(divisor));
		}
		else
		{
			return 0;
		}
	}

	int divide(int dividend, int divisor) {
		if (dividend == 0)
			return 0;
		
		if (divisor == 1) return dividend;	
		if (divisor == -1) return (dividend == INT_MIN) ? INT_MAX : -dividend;
		bool signal = false;//默认为正号
		if (dividend < 0 && divisor > 0 || dividend > 0 && divisor < 0)
			signal = true;

		long long res = abs(my_divide(abs(dividend), abs(divisor)));
		
		if (signal)
			return -res;
		else
			return res;
	}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值