一.题目描述以及来源
给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 '*'、除号 '/' 以及求余符号 '%' 。
注意:
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/xoh6Oh
例子:
- 输入:a = 15, b = 2
- 输出:7
- 解释:15/2 = truncate(7.5) = 7
- 输入:a = 7, b = -3
- 输出:-2
- 解释:7/-3 = truncate(-2.33333..) = -2
- 输入:a = 0, b = 1
- 输出:0
- 输入:a = 1, b = 1
- 输出:1
| a=15 | b=2 | k=0 |
| 15>=b(a>=b) | a=13 | k=1 |
| 15-2>=b | k=2 | |
| 13-2>=b | 3 | |
| 11-2>=b | 4 | |
| 9-2>=b | 5 | |
| 7-2>=b | 6 | |
| 5-2>=b | 7 | |
| 3-2 | end |
因为不能用除法,所以只能使用减法去实现除法。
实现的代码如下:
- public static void Divide(int a, int b)
- {
- //int sign = 1;
- //if((a>0 && b<0)||(a<0 && b > 0))
- //{
- // sign= -1;
- //}
- int sign = (a > 0) ^ (b > 0) ? -1 : 1;
- a=Math.Abs(a); b=Math.Abs(b);
- int res = 0;
- while(a>=b)
- {
- a=a-b;
- res++;
- }
- if(sign==-1)
- {
- res = -res;
- }
- System.Console.WriteLine(res);
- }
此外还需要考虑,除法的符号,以及边界问题
- //时间复杂度是O(n),
- public static int DivideRange(int a, int b)
- {
- //32位最大值: 2^31-1=2147483647
- //32为最小值:-2^31=—2147483648
- //—2147483648/(-1)=2147483648>—2147483647 越界
- if ((a == (-2147483648)) && (b == (-1))){
- return 2147483647;
- }
- int sign = (a > 0) ^ (b > 0) ? -1 : 1;
- //Math.Abs(—2147483648)=—2147483648 所以我们将正数转成负数去计算
- if (a > 0)
- {
- a = -a;
- }
- if (b > 0)
- {
- b = -b;
- }
- int res = 0;
- //-7 /-2 =3 ,都是负数除法 转成 数学,循环是<= 例如 -7<=-2 ,继续循环
- while (a <= b)
- {
- a = a - b;
- res++;
- }
- if (sign == -1)
- {
- res = -res;
- }
- return res;
- }
上面为解体的完整代码,需要注意的有:
1.范围时,注意范围的边界(最小值/-1 会越界,最小值取正数 会保持原值)
2.将所有数转成负数去进行计算,因为最大值可以取相反数,最小值相反数越界
3.原本数字都变成正数的时候,判断是a>=b,作为循环的条件。转成负数计算的时候,循环的条件是a<=b
4.在c#中Integer.MIN_VALUE为
-
- int max = int.MaxValue;
- int min = int.MinValue;
此思路看不懂的话可以去看看leetcode讲解视频:简单易懂Java/C++ /Python/js/go - 整数除法(剑指) - 整数除法 - 力扣(LeetCode)

- public static int DivideVersion2(int a, int b)
- {
- //32位最大值: 2^31-1=2147483647
- //32为最小值:-2^31=—2147483648
- //—2147483648/(-1)=2147483648>—2147483647 越界
- if ((a == (-2147483648)) && (b == (-1)))
- {
- return 2147483647;
- }
- int sign = (a > 0) ^ (b > 0) ? -1 : 1;
- //Math.Abs(—2147483648)=—2147483648 所以我们将正数转成负数去计算
- if (a > 0)
- {
- a = -a;
- }
- if (b > 0)
- {
- b = -b;
- }
- int res = 0;
-
- // 22/7
- while (a <= b)
- {
- int value = b;
- int k = 1;
- while (a < value + value)
- {
- k = k + k;
- value = value + value;
- }
- res += k;
- a = a - value;
-
- }
- if (sign == -1)
- {
- res = -res;
- }
- System.Console.WriteLine(res);
- return res;
- }
此方法会超时,而且会有越域的情况
在三的解题思路之上,我们知道我们可以实行b*2去减去a一半的情况。将b*2转换成b<<2,b往左移一位。

- public class Solution {
- public int Divide(int a, int b) {
- if ((a == int.MinValue) && (b == (-1)))
- {
- return int.MaxValue;
- }
- int res = 0;
-
- if (b == int.MinValue) {
- return a == b? 1 : 0;
- }
- // 被除数先减去一个除数
- if (a == int.MinValue) {
- a -= -Math.Abs(b);
- res += 1;
- }
-
-
- int sign = (a > 0) ^ (b > 0) ? -1 : 1;
- a = Math.Abs(a); b = Math.Abs(b);
-
- for(int i = 31; i >= 0; i--)
- {
- if ((a >> i) - b >= 0)
- {
- if (res > int.MaxValue - (1 << i)) {
- return int.MinValue;
- }
- a=a-(b<
- res = res + (1<
- }
- }
- if (sign == -1)
- {
- res = -res;
- }
- return res;
- }
- }
上面for循环内实现了整个逻辑,需要注意的是i=0是表示-b本身,所以需要i>=0.
以下是处理边界值的代码,测试之前没发现。
-
- if (b == int.MinValue) {
- return a == b? 1 : 0;
- }
- // 被除数先减去一个除数
- if (a == int.MinValue) {
- a -= -Math.Abs(b);
- res += 1;
- }
-
相关阅读:
开源医疗大模型排行榜: 健康领域大模型基准测试
java智慧校园信息管理系统源码带微信小程序
为什么在使用onnxruntime-gpu下却没有成功调用GPU?
计算机毕业设计Java知识管理系统(源码+系统+mysql数据库+Lw文档)
设计模式 - 命令模式
【面经】特斯拉大数据开发笔经
通用的方法在任何云VM上安装Mikrotik的Cloud Hosted Router
三种常见的移动底盘运动学模型分析
二进制部署kubernetes集群的推荐方式
C语言学习之路(基础篇)—— 数据类型 02
-
原文地址:https://blog.csdn.net/hellolianhua/article/details/128100072