Skip to content

Commit fb86e87

Browse files
committed
29.两数相除,二分查找
1 parent dea3835 commit fb86e87

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

leetcode_Java/DoneTitle.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
23. 合并K个升序链表
1717
24. 两两交换链表中的节点
1818
25. K 个一组翻转链表
19+
29. 两数相除
1920
31. 下一个排列
2021
32. 最长有效括号
2122
33. 搜索旋转排序数组

leetcode_Java/DoneType.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@
220220

221221

222222
十、数学
223+
29. 两数相除(二分查找)
223224
69. x 的平方根(二分查找)
224225
470. 用 Rand7() 实现 Rand10()(拒绝采样)
225226

leetcode_Java/Solution0029.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// 29. 两数相除
2+
3+
4+
/*
5+
二分查找:
6+
1、题目限定了不能使用乘法、除法和 mod 运算符
7+
2、通过位运算实现一个「倍增乘法」
8+
3、对于x除以y,结果 x/y 必然落在范围 [0,x] 内,对该范围进行二分查找
9+
4、数字太大时计算可能溢出,所以全部用long类型,最终结果再转成int类型
10+
5、处理标记结果正负号,运算过程用正数,最后再添加正负号
11+
6、计算中点位置时 (left + rigth + 1) / 2 的原因,假设最终剩下两个数
12+
1)(left + rigth + 1) / 2 会使中点位于右边的数,当右边的数乘积大于被除数时,会收缩右边界,最后只剩下左边的数,左边的数刚好是商取整的值
13+
2)(left + rigth) / 2 会使中点位于左边的数,当左边的数乘积小于被除数时,会收缩左边界,但是中点和左边界在同一位置上,所以会陷入死循环
14+
7、收缩边界
15+
1)中点乘积 <= 被除数时,收缩左边界,由于中点乘积是小于,中点可能是目标值,所以要包括中点,即 left = mid
16+
2)中点乘积 > 被除数时,收缩右边界,由于中点乘积是大于,中点不可能是目标值,所以不用包括中点,即 rigth = mid - 1
17+
*/
18+
class Solution {
19+
public int divide(int dividend, int divisor) {
20+
long x = dividend, y = divisor;
21+
boolean isNeg = false;
22+
if ((x < 0 && y > 0) || (x > 0 && y < 0)) {
23+
isNeg = true;
24+
}
25+
x = x < 0 ? -x : x;
26+
y = y < 0 ? -y : y;
27+
long left = 0, rigth = x;
28+
while (left < rigth) {
29+
long mid = (left + rigth + 1) / 2;
30+
if (multiply(mid, y) <= x) {
31+
left = mid;
32+
} else {
33+
rigth = mid - 1;
34+
}
35+
}
36+
long res = isNeg ? -left : left;
37+
if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) {
38+
return Integer.MAX_VALUE;
39+
}
40+
return (int) res;
41+
}
42+
43+
private long multiply(long a, long b) {
44+
long res = 0;
45+
while (b > 0) {
46+
if ((b & 1) == 1) {
47+
res += a;
48+
}
49+
b >>= 1;
50+
a += a;
51+
}
52+
return res;
53+
}
54+
}

0 commit comments

Comments
 (0)