刷题原则:
- 尽可能自己实现一遍代码,跑通示例
- 无论是否AC,看一看大神解法
- 看完大神解法后,无提示情况下重现一遍,找到遗漏的关键点
- 做笔记,当时理解上的困难点尽可能说明
剑指 Offer II 001. 整数除法
题目描述【简单】
给定两个整数 a
和 b
,求它们的除法的商 a/b
,要求不得使用乘号 '*'
、除号 '/'
以及求余符号 '%'
;
整数除法的结果应当截去(truncate
)其小数部分,例如:truncate(8.345) = 8
以及 truncate(-2.7335) = -2 ;
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2^31−1]
。本题中,如果除法结果溢出,则返回 2^31−1 。
输入:-2^31 <= a, b <= 2^31 - 1; b != 0
示例:
输入: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
代码:
根据错误反馈,不断改正,得到的:
class Solution {
public:
int divide(int a, int b) {
int count = 0, flag = 0;
if (a==0) return 0; // 需单独考虑,否则count--
// 除法结果溢出?
if ((a>0&&b<0)||(a<0&&b>0)) flag = 1;
// 需考虑a、b为负数的情况
a = abs(a); b = abs(b); // a=7, b=-3, c=-2
while (a>0) {
a -= b;
count++;
}
if (a) count--; // 刚好减到0就不用减1了
if (flag) count = 0-count;
return count;
}
};
因为不知道怎么判断溢出,去看了官方解答LeetCode:
// 考虑被除数为最小值的情况
// [−2^31, 2^31−1]
// 若除法结果溢出,则返回2^31−1
// INT_MIN==−2^31,INT_MAX==2^31−1
if (a == INT_MIN) {
if (b == 1) {
return INT_MIN;
}
if (b == -1) {
return INT_MAX;
}
}
// 考虑除数为最小值的情况
if (b == INT_MIN) {
return a == INT_MIN ? 1 : 0;
}
但是依然有测试错误:
通过测试用例:910 / 992
输入:-2147483648 2 输出:1 预期结果:-1073741824
即使这里不出现错误,应该也会有超时的问题吧。
如果我们将被除数和除数都变为正数,那么可能会导致溢出。
例如当被除数为−2^31时,它的相反数2^31产生了溢出。
因此,我们考虑将被除数和除数都变为负数,就不会有溢出的问题了,在编码时只需要考虑1种情况。
算法思路:二分查找
在考虑【快速乘】时,A + B可能会产生溢出,因此我们必须将判断改为 A < C - B是否成立。
class Solution {
public:
int divide(int a, int b) {
// 考虑a, b溢出
// 转化为负数
// 快速乘
auto quickAdd = [](int y, int z, int x) {
// x 和 y 是负数,z 是正数
// 需要判断 z * y >= x 是否成立
int result = 0, add = y;
while (z) {
if (z & 1) {
// 需要保证 result + add >= x
if (result < x - add) {
return false;
}
result += add;
}
if (z != 1) {
// 需要保证 add + add >= x
if (add < x - add) {
return false;
}
add += add;
}
// 不能使用除法
z >>= 1;
}
return true;
};
int left = 1, right = INT_MAX, ans = 0;
while (left <= right) {
// 注意溢出,并且不能使用除法
int mid = left + ((right - left) >> 1);
bool check = quickAdd(b, mid, a);
if (check) {
ans = mid;
// 注意溢出
if (mid == INT_MAX) {
break;
}
left = mid + 1;
}
else {
right = mid - 1;
}
}
return rev ? -ans : ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/xoh6Oh/solution/zheng-shu-chu-fa-by-leetcode-solution-3572/
来源:力扣(LeetCode)
理解中……