29. Divide Two Integers

LeetCode medium оригинал: C# #bit-manipulation #csharp #leetcode #math #medium
Учитывая два целых числа: делимое и делитель, разделите два целых числа, не используя операторы умножения, деления и модификатора.

Целочисленное деление должно сокращаться до нуля, что означает потерю дробной части. Например, 8,345 будет сокращено до 8, а -2,7335 будет сокращено до -2.

Возвращает частное после деления делимого на делитель.

Примечание. Предположим, мы имеем дело со средой, которая может хранить целые числа только в пределах 32-битного целого диапазона со знаком: [−2^31, 2^31 − 1]. В этой задаче, если частное строго больше 2^31 - 1, верните 2^31 - 1, а если частное строго меньше -2^31, верните -2^31.

C# решение

сопоставлено/оригинал
public class Solution {
    public int Divide(int dividend, int divisor) {
        if(divisor == 0 || dividend == int.MinValue && divisor == -1) return int.MaxValue;
        
        int sign = (dividend < 0 ^ divisor < 0) ? -1 : 1, result = 0;
        
        long m = Math.Abs((long)dividend), n = Math.Abs((long)divisor);
        
        while(m >= n)
        {
            long subN = n;
            for(int subCount = 1; m >= subN; subCount <<= 1, subN <<= 1)
            {
                m -= subN;
                result += subCount;
            }
        }
        
        return sign == 1 ? result : (result - result - result);
    }
}

C++ решение

auto-draft, проверить перед отправкой
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public int Divide(int dividend, int divisor) {
        if(divisor == 0 || dividend == int.MinValue && divisor == -1) return int.MaxValue;
        
        int sign = (dividend < 0 ^ divisor < 0) ? -1 : 1, result = 0;
        
        long m = abs((long)dividend), n = abs((long)divisor);
        
        while(m >= n)
        {
            long subN = n;
            for(int subCount = 1; m >= subN; subCount <<= 1, subN <<= 1)
            {
                m -= subN;
                result += subCount;
            }
        }
        
        return sign == 1 ? result : (result - result - result);
    }
}

Java решение

сопоставлено/оригинал
public int divide(int dividend, int divisor) {
  long result = divideLong(dividend, divisor);
  return result > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)result;
}

// It's easy to handle edge cases when
// operate with long numbers rather than int
public long divideLong(long dividend, long divisor) {
  
  // Remember the sign
  boolean negative = dividend < 0 != divisor < 0;
  
  // Make dividend and divisor unsign
  if (dividend < 0) dividend = -dividend;
  if (divisor < 0) divisor = -divisor;
  
  // Return if nothing to divide
  if (dividend < divisor) return 0;
  
  // Sum divisor 2, 4, 8, 16, 32 .... times
    long sum = divisor;
    long divide = 1;
    while ((sum+sum) <= dividend) {
      sum += sum;
      divide += divide;
    }
    
    // Make a recursive call for (devided-sum) and add it to the result
    return negative ? -(divide + divideLong((dividend-sum), divisor)) :
      (divide + divideLong((dividend-sum), divisor));
}

JavaScript решение

сопоставлено/оригинал
var divide = function(dividend, divisor) {    if(dividend===0) return 0;
    let signal = 1;    if(dividend<0){
        signal *= -1;    }
    if(divisor<0){        signal *= -1;
    }    dividend = Math.abs(dividend);
    divisor = Math.abs(divisor);    
    let result = help(dividend, divisor)*signal;    if(result>Math.pow(2,31)-1){
        result = Math.pow(2,31)-1;    }else if(result<-1*Math.pow(2,31)){
        result = Math.pow(2,31)*(-1);    }
    return result;    
        function help(dividend, divisor){            if(dividend < divisor) return 0;
            let res = 0;            let origDivisor = divisor;
            let prev = 0;            while(dividend>=divisor){
                if(res===0){                    res += 1;
                }else{                    res += res;
                }                prev = divisor;
                divisor += divisor;            }
            dividend -= prev;            res += help(dividend, origDivisor);
            return res;        }
};

Python решение

сопоставлено/оригинал
class Solution(object): 
    def divide(self, dividend, divisor): 
        """ 
        :type dividend: int 
        :type divisor: int 
        :rtype: int 
        """ 
        if abs(divisor) == 1: 
            dividend = divisor * dividend 
            if dividend > 2**31 - 1: 
                return 2**31 - 1 
 
            if dividend < -2**31: 
                return -2**31 
 
            return dividend 
 
        quotient = 0 
        sign = 1 
        if dividend * divisor < 0: 
            sign = -1 
 
        if dividend < 0: dividend = -dividend 
        if divisor < 0: divisor = -divisor 
 
        i = 1 
        sum_all = 0 
        while sum_all <= dividend: 
            if dividend - sum_all < divisor * i: 
                i = 1 
            quotient += i 
            sum_all += divisor * i 
            i += 1 
 
        return (quotient - 1) * sign

Go решение

сопоставлено/оригинал
func divide(dividend int, divisor int) int {
    c := 0
    dividendS, r := SplitSignAndNum(dividend)
    divisorS, d := SplitSignAndNum(divisor)
    for r >= d {
        r = r - d
        c++
    }
    
    result := c
    
    if dividendS < 0 || divisorS < 0 {
        if !(dividendS < 0 && divisorS < 0) {
            result = -c
        }
    }
    
    if result < -2147483648 {
        return -2147483648
    } else if result > 2147483647 {
        return 2147483647
    }
    
    return result
}

func SplitSignAndNum(i int) (int,int) {
    if i < 0 {
        return -1, -i
    }
    return 1, i
}

Данный код представляет собой класс `Solution`, в котором содержится метод `Divide`, реализующий операцию деления без использования оператора деления. Этот метод выполняет деление `dividend` на `divisor` и возвращает результат деления. Вот пояснение к данному методу:

1. Метод `Divide` принимает два целых числа `dividend` и `divisor` и возвращает результат деления `dividend` на `divisor`.

2. В начале метода проверяется специальный случай: если `divisor` равен 0 или если `dividend` равен `int.MinValue` и `divisor` равен -1, то метод возвращает `int.MaxValue`. Это делается для предотвращения переполнения в случае деления на 0 или разделения `int.MinValue` на -1.

3. Затем определяется знак результата деления на основе знаков `dividend` и `divisor`. Если знаки разные, то результат будет отрицательным, иначе - положительным.

4. Затем переменные `m` и `n` инициализируются как модули от `dividend` и `divisor`, но уже `long`, чтобы избежать переполнения в процессе деления.

5. Запускается цикл `while`, который продолжается, пока `m` больше или равен `n`. Внутри цикла выполняется итеративное вычитание и увеличение результата на основе сдвига влево.

6. Наконец, возвращается результат деления, который корректируется в зависимости от знака в соответствии с вычисленным знаком. Если знак равен -1, результат умножается на -1.

Этот метод реализует алгоритм вычитания для нахождения результата деления без использования оператора деления, а также управляет специальными случаями, чтобы избежать переполнения.

Вакансии для этой задачи

Показаны активные вакансии с пересечением по тегам задачи.

Все вакансии
Активных вакансий пока нет.