leetcode29 :Divide Two Integers

一:题目描述

英文描述:
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, which means losing its fractional part. For example, truncate(8.345) = 8 and truncate(-2.7335) = -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].
    中文描述:

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = >-2

提示:

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

二:题目分析

由于不能使用 乘法 除法 与取余算法 所以自然想到由循环减法来写出的算法。但是单纯的减法循环遇到
-2147483648 / 1 时算法耗时将会很大到超时。所以要采取递归来优化算法。
而此题目也有些要注意的地方如当 -2147483648 / -1时 由于int 只能运算到2147483647,所以存在一个
越界的问题。

分析算法:首先要先解决 -2147483648 / -1这类情况可以让其直接返回 INT_MAX.
                  然后设置一个 flag 来帮助记录符号,再将其全部转化为 long 型的正数。
                  然后在核心的算法中使用二分法也就是将除数来进行移位的操作。
for example:以 100 / 3 为例子。
                  1. 当 3 取移位到 3*2^6dividend < divisor了 所以这时的判断条件为
                   dividend > = (divisor+divisor)
                  2. 所以此时的 相当于 3*2^5 即32个3,达到了除法的目的,
                  3. 然后将dividend = dividend - 3*2^5然后再将其进行递归操作 递归的出口为
                   dividend < divisor

即用移位运算符将除数移位达到二分的目的。

三:代码

#include 
using namespace std;
class Solution {
public:
    int divide(int dividend, int divisor)
     {
        if(dividend == 0)              //被除数为 0 时,返回 0 
        {
            return 0;
        }
        if(divisor == 1) 			  //除数为 1 时 返回 被除数
        {
            return dividend;
        }
        if(divisor == -1)			//Notes 这里的溢出要考虑
        {
            if(dividend>INT_MIN) 
            {
                return -dividend;
            }
            return INT_MAX;
        }
        long a = dividend;
        long b = divisor;
        int flag = 1;
        if(a<0 && b>0||a>0 && b<0)
        {
            flag = -1;
        }   
        a = a>0?a:-a;
        b = b>0?b:-b;
        long res = div(a,b);
        if(flag>0)
        {
            return res;
        }
        return -res;
    }
    int div(long x, long y)				//核心算法
    {  
        if(x < y)			//递归出口
        {
            return 0;
        }
        long count = 1;
        long t = y; 
        while((t+t)<=x)			//注意这里一定要写出 t+t 如果写出 t <<=1 t的值将会发生改变 影响后面的移位
        {
            count <<=1; 		//初始为 1 记录一共多少个 t
            t <<=1; 
        }
        return count + div(x-t,y);
    }
};

四:总结

这是一道 medium 的算法题 自己当时写的时候由于没有用递归 和 移位 而超出了时间的限制,所以看到别人的solution之后自己也进行了反思,也慢慢的深入了解着二分查找的soul。

你可能感兴趣的:(Algorithm,problems)