当前位置: 首页 > article >正文

剑指 Offer II 001. 整数除法


comments: true
edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20001.%20%E6%95%B4%E6%95%B0%E9%99%A4%E6%B3%95/README.md

剑指 Offer II 001. 整数除法

题目描述

给定两个整数 ab ,求它们的除法的商 a/b ,要求不得使用乘号 '*'、除号 '/' 以及求余符号 '%' 。

 

注意:

  • 整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
  • 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1

 

示例 1:

输入:a = 15, b = 2
输出:7
解释:15/2 = truncate(7.5) = 7

示例 2:

输入:a = 7, b = -3
输出:-2
解释:7/-3 = truncate(-2.33333..) = -2

示例 3:

输入:a = 0, b = 1
输出:0

示例 4:

输入:a = 1, b = 1
输出:1

 

提示:

  • -231 <= a, b <= 231 - 1
  • b != 0

 

注意:本题与主站 29 题相同:https://leetcode.cn/problems/divide-two-integers/

 

解法

方法一:模拟 + 快速幂

除法本质上就是减法,题目要求我们计算出两个数相除之后的取整结果,其实就是计算被除数是多少个除数加上一个小于除数的数构成的。但是一次循环只能做一次减法,效率太低会导致超时,可借助快速幂的思想进行优化。

需要注意的是,由于题目明确要求最大只能使用 32 位有符号整数,所以需要将除数和被除数同时转换为负数进行计算。因为转换正数可能会导致溢出,如当被除数为 INT32_MIN 时,转换为正数时会大于 INT32_MAX

假设被除数为 a a a,除数为 b b b,则时间复杂度为 O ( log ⁡ a × log ⁡ b ) O(\log a \times \log b) O(loga×logb),空间复杂度 O ( 1 ) O(1) O(1)

Python3
class Solution:
    def divide(self, a: int, b: int) -> int:
        INT_MIN,INT_MAX=-2**31,2**31-1
        if a==INT_MIN and b==-1:return INT_MAX
        if b==-1:return min(max(-a,INT_MIN),INT_MAX)
        if b==1:return min(max(a,INT_MIN),INT_MAX)

        neg=(a>0) ^ (b>0)
        #转负防溢
        a,b=-abs(a),-abs(b)
        #快速幂负数整除
        res=0
        while a<=b: #步骤1)、2)出现循环
            cur_v=b
            cur_num=1

            # 1)按2倍递增找最大偶数商 2 4 8 ... 
            while a<= cur_v<<1:
                cur_v<<=1
                cur_num<<=1
            # 2)含 a-偶数商*b, a-奇数商
            a-=cur_v
            res+=cur_num
        return -res if neg else res
Java
class Solution {
    public int divide(int a, int b) {
        if (b == 1) {
            return a;
        }
        if (a == Integer.MIN_VALUE && b == -1) {
            return Integer.MAX_VALUE;
        }
        boolean sign = (a > 0 && b > 0) || (a < 0 && b < 0);
        a = a > 0 ? -a : a;
        b = b > 0 ? -b : b;
        int ans = 0;
        while (a <= b) {
            int x = b;
            int cnt = 1;
            while (x >= (Integer.MIN_VALUE >> 1) && a <= (x << 1)) {
                x <<= 1;
                cnt <<= 1;
            }
            ans += cnt;
            a -= x;
        }
        return sign ? ans : -ans;
    }
}
C++
class Solution {
public:
    int divide(int a, int b) {
        if (b == 1) {
            return a;
        }
        if (a == INT_MIN && b == -1) {
            return INT_MAX;
        }
        bool sign = (a > 0 && b > 0) || (a < 0 && b < 0);
        a = a > 0 ? -a : a;
        b = b > 0 ? -b : b;
        int ans = 0;
        while (a <= b) {
            int x = b;
            int cnt = 1;
            while (x >= (INT_MIN >> 1) && a <= (x << 1)) {
                x <<= 1;
                cnt <<= 1;
            }
            ans += cnt;
            a -= x;
        }
        return sign ? ans : -ans;
    }
};
Go
func divide(a int, b int) int {
	if b == 1 {
		return a
	}
	if a == math.MinInt32 && b == -1 {
		return math.MaxInt32
	}

	sign := (a > 0 && b > 0) || (a < 0 && b < 0)
	if a > 0 {
		a = -a
	}
	if b > 0 {
		b = -b
	}
	ans := 0

	for a <= b {
		x := b
		cnt := 1
		for x >= (math.MinInt32>>1) && a <= (x<<1) {
			x <<= 1
			cnt <<= 1
		}
		ans += cnt
		a -= x
	}

	if sign {
		return ans
	}
	return -ans
}
TypeScript
function divide(a: number, b: number): number {
    if (b === 1) {
        return a;
    }
    if (a === -(2 ** 31) && b === -1) {
        return 2 ** 31 - 1;
    }

    const sign: boolean = (a > 0 && b > 0) || (a < 0 && b < 0);
    a = a > 0 ? -a : a;
    b = b > 0 ? -b : b;
    let ans: number = 0;

    while (a <= b) {
        let x: number = b;
        let cnt: number = 1;

        while (x >= -(2 ** 30) && a <= x << 1) {
            x <<= 1;
            cnt <<= 1;
        }

        ans += cnt;
        a -= x;
    }

    return sign ? ans : -ans;
}
C#
public class Solution {
    public int Divide(int a, int b) {
        if (b == 1) {
            return a;
        }
        if (a == int.MinValue && b == -1) {
            return int.MaxValue;
        }
        bool sign = (a > 0 && b > 0) || (a < 0 && b < 0);
        a = a > 0 ? -a : a;
        b = b > 0 ? -b : b;
        int ans = 0;
        while (a <= b) {
            int x = b;
            int cnt = 1;
            while (x >= (int.MinValue >> 1) && a <= (x << 1)) {
                x <<= 1;
                cnt <<= 1;
            }
            ans += cnt;
            a -= x;
        }
        return sign ? ans : -ans;
    }
}
Swift
class Solution {
    func divide(_ a: Int, _ b: Int) -> Int {
        if b == 1 {
            return a
        }
        if a == Int32.min && b == -1 {
            return Int(Int32.max)
        }
        let sign = (a > 0 && b > 0) || (a < 0 && b < 0)
        var a = a > 0 ? -a : a
        let b = b > 0 ? -b : b
        var ans = 0
        while a <= b {
            var x = b
            var cnt = 1
            while x >= (Int32.min >> 1) && a <= (x << 1) {
                x <<= 1
                cnt <<= 1
            }
            ans += cnt
            a -= x
        }
        return sign ? ans : -ans
    }
}

http://www.kler.cn/a/524557.html

相关文章:

  • 算法的时间复杂度
  • cursor软件的chat和composer分别是什么
  • 【LLM】deepseek多模态之Janus-Pro和JanusFlow框架
  • 第19篇:python高级编程进阶:使用Flask进行Web开发
  • 基于SpringBoot的高校一体化服务平台的设计与实现(源码+SQL脚本+LW+部署讲解等)
  • 通义灵码插件保姆级教学-IDEA(安装及使用)
  • 步进电机加减速公式推导
  • three.js用粒子使用canvas生成的中文字符位图材质
  • 【Proteus仿真】【51单片机】简易计算器系统设计
  • python-leetcode-从中序与后序遍历序列构造二叉树
  • 【Spark速通】
  • MV结构下设置Qt表格的代理
  • EXCEL教程:如何打开Excel隐藏部分?
  • JavaScript - Web APIs(上)
  • 基于Arcsoft的人脸识别
  • doris:异常数据处理
  • DeepSeek部署教程(基于Ollama)
  • 具身智能研究报告
  • 展示统计信息收集情况
  • redis缓存和springboot缓存包冲突怎么办
  • 再见了流氓软件~~
  • 什么是AGI
  • PyTorch中的movedim、transpose与permute
  • [特殊字符] x-cmd pkg | fzf (1) - 强大的模糊搜索工具,一条命令颠覆你的命令行交互体验
  • Autogen_core 测试代码:test_cache_store.py
  • 003 mapper代理开发方式-注解方式