zoukankan      html  css  js  c++  java
  • LeetCode-29. Divide Two Integers

    一、问题描述

      实现两个int数的相除,返回它们相除的int值,但是不能使用乘法、除法、和mod运算。

    二、问题解决

      最开始能想到的方法就是不断用被除数去减除数,等到被除数小于0的时候相减了多少轮就是两数相除的int值,但是一个很大的数除以一个很小的数可能会超时,实验一下,果然会超时。

      要解决这个问题还需要使用减法,只是要想办法提高相减的次数。这里使用右移运算,假设被除数为M,除数为N,M第一次减去N,第二次减去N<<1,第三次减去(N<<1)<<1,使被除数快速的减小,当发现N右移n次后比M大的时候,用M减去N右移n-1次的结果,然后又重复上面的寻找n的步骤。由于每次是从N开始,相当于每次N*2的方式增大,但是有不用到乘法。

      举个例子:假设使用M=15除N=3,第一次使用15-3,发现12大于3,然后又使用15-(3<<1)=9,发现9还是比3大,然后用15-((3<<1)<<1)=3,发现还是不小于3,于是使用15-(((3<<1)<<1)<<1)=-9,是小于3的,于是令M=15-((3<<1)<<1)=3,次数n=n+(1<<1)<<1=4(初始n=0)。再使用M(现在等于3)去减N(还是从初始N开始),发现M-N<N,所以这次不用右移,n=n+1,所以n=5,即两数相除等于5。

      代码实现:

    int divide(int dividend, int divisor) {
        if (divisor == 0 || (dividend == INT_MIN && divisor==-1))return INT_MAX;
        int sig = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1;
        int time = 0;
        long long d1 = labs(dividend);
        long long d2 = labs(divisor);
        while (d1 >= d2) {
            long long temp = d2, a = 1;
            while (d1 >= (temp << 1)) {
                temp <<= 1;
                a <<= 1;
            }
            d1 -= temp;
            time += a;
        }
        return sig == 1 ? time : -time;
    }
    
    int main()
    {
        cout << divide(1,-1) << endl;
    
        system("pause");
        return 0;
    }

     三、问题思考

      1、在这次的代码中,对dividend和divisor求绝对值的时候使用了long long类型,但凡考虑绝对值的情况一定考虑INT_MAX和INT_MIN的情况,这里如果对INT_MIN去绝对值就会溢出,所以使用long long类型。

      2、总结一下c++各个数据类型的范围:

    数据类型名称 字节数 别名 取值范围
    int 4 signed,signed int 操作系统决定,即与操作系统的"字长"有关(一般为4个字节)
    unsigned int 4 unsigned 由操作系统决定,即与操作系统的"字长"有关(一般为4个字节)
    __int8 1 char,signed char –128 到 127
    __int16 2 short,short int,signed short int –32,768 到 32,767
    __int32 4 signed,signed int –2,147,483,648 到 2,147,483,647
    __int64 8 –9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
    bool 1 false 或 true
    char 1 signed char –128 到 127
    unsigned char 1 0 到 255
    short 2 short int,signed short int –32,768 到 32,767
    unsigned short 2 unsigned short int 0 到 65,535
    long 4或8 long int,signed long int –2,147,483,648 到 2,147,483,647
    long long 8 none (but equivalent to __int64) –9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
    unsigned long 4 unsigned long int 0 到 4,294,967,295
    enum * 由操作系统决定,即与操作系统的"字长"有关
    float 4 3.4E +/- 38 (7 digits)
    double 8 1.7E +/- 308 (15 digits)
    long double 8 1.7E +/- 308 (15 digits)
    wchar_t 2 __wchar_t 0 到 65,535

      在32位系统之中,long为32位,64位系统之中,long为64位。int始终为32位。

      3、代码中在右移的时候使用变量a,a也是long long 类型,发现使用int值时会超时,而使用long long就不会。思考的是会不会64位系统之中64位数据移位运算会比32位数据移位运算更快?随手下了下面的例子:

    long long looptime = 100000000;
    
    void test2() {
        long long a;
        for (int t = 0; t < looptime; t++) {
            for (auto i = 0; i < 30; i++) {
                a << i;
            }
        }
    }
    
    void test1() {
        int a;
        for (int t = 0; t < looptime; t++) {
            for (auto i = 0; i < 30; i++) {
                a << i;
            }
        }
    }
    
    int main()
    {
        double start1, stop1, duration1, start2, stop2, duration2;
        start1 = clock();
        test1();
        stop1 = clock();
        start2 = clock();
        test2();
        stop2 = clock();
        duration1 = ((double)(stop1 - start1)) / CLK_TCK;
        duration2 = ((double)(stop2 - start2)) / CLK_TCK;
        cout << duration1 << " "<< duration2 <<endl;
    
        system("pause");
        return 0;
    }

       发现事实好像并不是这样,和long long 还是int类型无关,倒是先算计算的一定比后计算的快,即duration1小于duration2,于是我改成两个测试函数一样,都使用int或都使用long long,发现还是这个结果。

      我又使用同一函数,时刻1使用int值,时刻2使用long long,发现结果也并不是这样,使用long long时间又是也高过int。

      没搞清楚这是为什么,希望以后能弄明白,现在先记在这里。

  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/likaiming/p/8316955.html
Copyright © 2011-2022 走看看