29. Divide Two Integers

Leetcode: https://leetcode.com/problems/divide-two-integers/

Given two integers dividend and divisor, divide two integers without using multiplication, division, and mod operator.

The integer division should truncate toward zero, which means losing its fractional part. For example, 8.345 would be truncated to 8, and -2.7335 would be truncated to -2.

Return the quotient after dividing dividend by divisor.

Note: Assume we are dealing with an environment that could only store integers within the 32-bit signed integer range: [−2^31, 2^31 − 1]. For this problem, if the quotient is strictly greater than 2^31 - 1, then return 2^31 - 1, and if the quotient is strictly less than -2^31, then return -2^31.

Example 1:

Input: dividend = 10, divisor = 3
Output: 3
Explanation: 10/3 = 3.33333.. which is truncated to 3.

Example 2:

Input: dividend = 7, divisor = -3
Output: -2
Explanation: 7/-3 = -2.33333.. which is truncated to -2.

Constraints:

  • -2^31 <= dividend, divisor <= 2^31 - 1
  • divisor != 0

Solution

Inspired by this solution.

But here, we ONLY use the int32/16/8, and DO NOT use long long or int64.

Suppose what we need to compute is a / b.

If we are permitted to use multiplication operation, then our code will be like:

int k = 1;
while (b * k <= a) k++;
return k;
// or
int k = 0;
while (a >= b) a -= b, k++;
return k;

However, * operation is not allowed to be used here. But we can use shift operation << to simulate *.

Consider a special case, if we are computing n / 32, then it's easy to see that we should return n >> 5, since 32 = 2^5.

For the common cases, they are similar. If we are computing 33 / 6,

  • First, find out the maximum k satisfying 6 * 2 ^ k <= 33. (Obviously, k = 2 here, and this means we can minus 2^k * 6 from 33, and this will cause our quotient increase 2^k.)
  • Then the remained number is 33 - 6 * 2^k = 9, continue computing the maximum k satisfying 6 * 2^k <= 9. (k = 0 here.)
  • The remained number is 3 now, and 3 can not be divided by 6.

Sum up all of the 2^k, we can get final quotient ret = 2^2 + 2 ^ 0 = 5.

From now, we can got 1st version of code.

#define SIGNBIT(x) (((uint32_t)(x) >> 31) & 1)
class Solution {
public:
    const int INTMIN = (1 << 31);
    const int INTMAX = ~INTMIN;
    int divide(int dividend, int divisor) 
    {
        if (dividend == INTMIN && divisor == -1) return INTMAX;
        
        uint8_t sign = SIGNBIT(dividend) ^ SIGNBIT(divisor);
        uint32_t a = abs(dividend), b = abs(divisor), ret = 0;
        
        while (a >= b)
        {
            uint32_t tmp = b, cnt = 1;
            while ((tmp << 1) <= a)
                tmp <<= 1, cnt <<= 1;
            a -= tmp, ret += cnt;
        }
        return sign ? -ret : ret;
    }
};

However, there is an issue since we are only permitted to use INT32.

Suppose the input is 0x80000000 / b, and b = 2 ^ k (e.g. 1, 2, 4, 8, 16 ...).

In the internal loop:

uint32_t tmp = b, cnt = 1;
while ((tmp << 1) <= a) tmp <<= 1, cnt <<= 1;

When tmp = b grows up to 0x80000000, tmp << 1 is still less equal than a because of the overflow!

Hence we add a if branch to handle this case.

#define SIGNBIT(x) (((uint32_t)(x) >> 31) & 1)
class Solution {
public:
    const int INTMIN = (1 << 31);
    const int INTMAX = ~INTMIN;
    int divide(int dividend, int divisor) 
    {
        if (dividend == INTMIN && divisor == -1) return INTMAX;
        
        uint8_t sign = SIGNBIT(dividend) ^ SIGNBIT(divisor);
        uint32_t a = abs(dividend), b = abs(divisor), ret = 0;
        
        if (a == INTMIN && (b & (b - 1)) == 0)
        {
            uint8_t cntZero = 0;
            while (b >> 1) b >>= 1, cntZero += 1;
            a >>= cntZero;
            return sign ? -a : a;
        }
        
        while (a >= b)
        {
            uint32_t tmp = b, cnt = 1;
            while ((tmp << 1) <= a)
                tmp <<= 1, cnt <<= 1;
            a -= tmp, ret += cnt;
        }
        return sign ? -ret : ret;
    }
};
posted @   sinkinben  阅读(81)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示