uacs2024

导航

leetcode 29. 两数相除 中等 未完全解决

29. 两数相除

首先是我自己写出来的方法,复杂度为O(n)

一、使用long类型

class Solution {
public:
    long divide2(long dividend,long divisor){
        if(dividend < 0 && divisor < 0)  return divide2(-dividend,-divisor);
        else if(dividend < 0 && divisor > 0)  return -divide2(-dividend,divisor);             
        else if(dividend > 0 && divisor < 0)  return -divide2(dividend,-divisor);
        if(divisor == 1) return dividend;
        if(dividend < divisor) return 0;
        long num = 0;
        while(dividend > 0){
            dividend -= divisor;
            num++;
        }
        if(dividend < 0)  return num-1;
        return num;
    }

    int divide(int dividend, int divisor) {
        long MAX = pow(2,31);
        long num = divide2(dividend,divisor);
        if(num > MAX-1)  return MAX-1;
        else if(num < -MAX)  return -MAX;
        return num;
    }
};

用时和消耗内存表现特别差

 二、不使用long类型

测试点会有很多  -2^31  2^31-1  1  -1 这些地方选。

特别是  -2^31  ,不能将它转换为正数,只能单防,剪枝

class Solution {
public:
    int divide2(int dividend,int divisor){
        if(dividend < 0 && divisor < 0)  return divide2(-dividend,-divisor);
        else if(dividend < 0 && divisor > 0)  return -divide2(-dividend,divisor);             
        else if(dividend > 0 && divisor < 0)  return -divide2(dividend,-divisor);
        if(dividend < divisor) return 0;
        int num = 0;
        while(dividend > 0){
            dividend -= divisor;
            num++;
        }
        if(dividend < 0)  return num-1;
        return num;
    }

    int divide(int dividend, int divisor){
        if(dividend == divisor)  return 1;
        if(divisor == INT_MIN)  return 0;
        if(dividend == INT_MIN && divisor == -1)  return INT_MAX;
        if(divisor == 1)  return dividend;
        if(divisor == -1)  return -dividend;
        if(dividend == INT_MIN){
            int num = 0;int flag;
            if(divisor > 0)    flag = 1;
            else    flag = -1;
            while(dividend < 0){
                dividend = dividend +  divisor*flag;
                num++;               
            }
            if(dividend != 0)    return (num-1)*-1*flag;
            return num*-1*flag;          
        }
        return divide2(dividend,divisor);
    }
};

内存表现好了一点,耗时还是很大

 最优的方法应该是使用快速乘

因为有数据范围限制,负数的范围比正数更大。所以题解基本上都是将两个数都转为负数进行计算

为了更好理解算法思想,我先使用long类型,两个数都转为正数

class Solution {
public:
    long divide2(long dividend,long divisor){
        bool flag = true;
        if(dividend > 0 && divisor < 0 || dividend < 0 && divisor > 0)  flag = false;
        if(dividend < 0)  dividend = -dividend;
        if(divisor < 0)  divisor = -divisor;
        
        vector<pair<long,long>> exp;
        for(long i = divisor,j = 1; i <= dividend; i += i, j += j){
            exp.push_back({i,j});  //将被除数的2^k倍数和2^k对应关系保存起来
        }

        int res = 0;
        for(int i = exp.size()-1; i >= 0; i--){
            if(exp[i].first <= dividend){
                res += exp[i].second;
                dividend -= exp[i].first;
            }
        }

        if(flag == false)  return -res;
        if(res == INT_MIN)  return INT_MAX;
        return res;
    }

    int divide(int dividend, int divisor){       
        if(dividend == divisor)  return 1;
        if(divisor == INT_MIN)  return 0;
        if(dividend == INT_MIN && divisor == -1)  return INT_MAX;
        if(divisor == 1)  return dividend;
        if(divisor == -1)  return -dividend;
        if(dividend == 0)  return 0;

        return divide2(dividend,divisor);
    }
};

不使用long ,两个数都转换为负数

class Solution {
public:
    int divide(int dividend, int divisor){       
        if(dividend == divisor)  return 1;
        if(divisor == INT_MIN)  return 0;
        if(dividend == INT_MIN && divisor == -1)  return INT_MAX;
        if(divisor == 1)  return dividend;
        if(divisor == -1)  return -dividend;
        if(dividend == 0)  return 0;

        bool flag = true;
        if(dividend > 0 && divisor > 0 || dividend < 0 && divisor < 0)  flag = false;
        if(dividend > 0)  dividend = -dividend;
        if(divisor > 0)  divisor = -divisor;
        if(dividend > divisor)  return 0;//被除数的绝对值比除数小

        vector<pair<int,int>> exp;
        for(int i = divisor,j = -1; i >= dividend; i += i, j += j){
            //一开始除数是大于被除数的
            exp.push_back({i,j});    ////将被除数的2^k倍数和2^k对应关系保存起来
            if(i < INT_MIN>>1)  break; //说明下一次i*2就会超过int的左范围了
            //if(i < INT_MIN/2)  break;
        }

        int res = 0;
        for(int i = exp.size()-1; i >= 0; i--){
            if(exp[i].first >= dividend){
                res += exp[i].second;
                dividend -= exp[i].first; //exp[i].first本身就是负的,越减只会让dividend越靠近0
            }
        }

        if(flag == false)  return -res;
        //if(res == INT_MIN)  return INT_MAX; //只有INT_MIN/1结果才是INT_MIN,但前面已经剪枝了
        return res;
    }
};

 

posted on 2024-11-12 17:12  ᶜʸᵃⁿ  阅读(1)  评论(0编辑  收藏  举报