[LeetCode]Divide Two Integers

Posted 乘风有时

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode]Divide Two Integers相关的知识,希望对你有一定的参考价值。

题目:

不用除法运算符,计算两个整数相除。

注意:

1、除数为零,

2.最小负数转为正数时溢出的情况。(-2147483648/-1 = 2147483648 > 2147483647)

3.正负号

/*******************************************************************************
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
*******************************************************************************/
#include<stdio.h>

#define MAX_INT 2147483647

int divide(int dividend, int divisor) {
        if(divisor == 0)return MAX_INT;//除数为零
        if(divisor == -1 && dividend == -2147483648)return MAX_INT;//被除数为int的最小数(-2147483648),除数为-1,此时由于int整数最大只能为2147483647,会溢出
    int flag = 1;
    if(dividend > 0){//计算符号
        dividend = -dividend;
        if(divisor > 0){
            divisor = -divisor;
        }else{
            flag = -1;
        }
    }else{
        if(divisor > 0){
            divisor = -divisor;
            flag = -1;
        }
    }

        int count = 0,result = 0;
    for(int i = 0;i > dividend;){//计算绝对值
        i += divisor;
        result--;
    }
        if(flag > 0){
        return -result;
      }else{
        return result;
      }
}

void main(){
    printf("%d\n",divide(2147483647,1));
}

但是上面的做法效率太低,无法通过。

考虑用左移的方法,速度更快。

思路:

1.为了避免溢出将数据变成long long型。

2.计算结果的符号

3.左移,找左移的最小位数,使得除数左移该位数时正好超过被除数。

4.从上面找到的位数开始每次减少一位,被除数减去当前左移的位数,结果加上1左移同样的位数的值。

数学表示:109/3 = 1101101/11

第三步即找到11000000 = 11 << 6 < 1101101 < 1100000 = 11 << 5中的6这个数,

第四步从5开始循环,每次减1,被除数109第一次循环减去96(1100000)得到13,如此减下去直到小于除数3;

/*******************************************************************************
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
*******************************************************************************/
#include<stdio.h>
#include<math.h>

#define MAX_INT 2147483647
typedef long long Long;//32位C编译器中long和int都是4字节,16位编译器中int是2字节long是4字节

int divide(int dividend, int divisor) {
        if(divisor == 0)return MAX_INT;
        int flag;
        Long dividendL,divisorL;
        if(dividend < 0){//计算符号,并转成long long类型
            flag = -1;
            dividendL = -(Long)dividend;
        }else{
            flag = 1;
            dividendL = (Long)dividend;
        }
        if(divisor > 0){
            divisorL = (Long)divisor;
        }else{
            flag = -flag;
            divisorL = -(Long)divisor;
        }

        int count = 0,result = 0;
        Long temp = divisorL;
        while(temp < dividendL){//左移,找到除数左移超过被除数的最小位数
            temp = temp << 1;
            count++;
        }

        for(int i = count - 1;i >= 0;i--){
            if(dividendL >= (divisorL << i)){
                dividendL = dividendL - (divisorL << i);
                result += (1 << i);
            }
        }
        
        if(dividendL == divisorL)result++;//若temp==dividendL时,此时dividendL==divisorL

        if(flag > 0){
            if(result < 0)return MAX_INT;
            return result;
        }else return -result;
}

void main(){
    printf("%d\n",divide(-2147483648,-1));
}

 

类似的还有要求自己实现pow(x,n)函数,同样用到左移。

思路如下:

1.首先记录n的正负,

2.然后用32位数组记录|n|的二进制表示方法,对应位置置1,表示最后计算平方的时候,当前位的结果要加到最终结果里面。

实际上不需要用数组存储,用按位与也可以一一取出对应的1.

3.计算32位中每位的x的乘方。并根据n的正负性给出结果。

数学表示:x^13 = x^8 * x^4 * x^1;

第二步即是求8、4、1,第三步求最后的乘积。

注意:

1.首先,特殊情况要单独考虑:x = 0.0;n=0。

2.由于n需要变成正数,所以要考虑n=-2147483648不能直接加负号转成正数的特殊情况。

3.最后要把n的符号加进去

 1 /************************************
 2 Implement pow(x, n).
 3 ************************************/
 4 #include<stdio.h>
 5 
 6 double myPow(double x, int n) {
 7     if(x == 0.0)return x;
 8     if(n == 0)return 1.0;
 9     //flag标记n的正负性,end表示indexs中最高位的1的下标
10     int i,flag = 0,end = -1;
11     int val = n;
12     int indexs[32] = {0};//标记n的二进制表示法
13     if(n == -2147483648){
14         indexs[31] = 1;
15         end = 31;
16         flag = 1;
17     }
18     else{
19         if(n < 0){
20             flag = 1;
21             val = -val;
22         }
23         for(i = 30;i >= 0;i--){
24             int temp = 1;
25             temp = temp << i;
26             if(val >= temp){
27                 val -= temp;
28                 indexs[i] = 1;
29                 if(end == -1)end = i;//end记录最高位
30             }
31         }
32     }
33     double result = 1.0;
34     double temps[32] = {0.0};
35     temps[0] = x;
36     if(indexs[0] == 1)result = result*temps[0];
37     for(i = 1;i <= end;i++){
38         temps[i] = temps[i - 1]*temps[i - 1];//求x^2^i
39         if(indexs[i] == 1)result = result*temps[i];
40     }
41     if(flag == 1) return 1.0/result;
42     return result;
43 }
44 
45 void main(){
46     printf("%lf\n",myPow(1.0000000001,-2147483648));
47 }

 

以上是关于[LeetCode]Divide Two Integers的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode Divide Two Integers

[LeetCode]Divide Two Integers

Divide Two Integers -- LeetCode

LeetCode 29. Divide Two Integers

Leetcode 29. Divide Two Integers

[LeetCode] 29. Divide Two Integers