-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMain1.java
110 lines (104 loc) · 3.33 KB
/
Main1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package JZOfferTuJi;
/*
* 二进制除法:
* 1.同为0,异为1.
* 2.被除数位数不够,商为0.
* 位数够,商为1.
* */
public class Main1 {
/* 最初版本
public int divide1(int a, int b){
// int sign = 1;
// if((a>0 && b<0) || (a<0 && b>0)){
// sign = -1;
// }
// 32位最大值:2^31 - 1 = 2147483647
// 32位最小值:-2^31 = -2147483648
if(a == Integer.MIN_VALUE && b == -1)
return Integer.MAX_VALUE;
int sign = (a > 0) ^ (b > 0) ? -1 : 1;
a = Math.abs(a);
b = Math.abs(b);
int res = 0;
while (a >= b){
a -= b;
res ++;
}
return sign * res;
}
*/
/*
public int divide2(int a, int b){
// 32位最大值:2^31 - 1 = 2147483647
// 32位最小值:-2^31 = -2147483648
if(a == Integer.MIN_VALUE && b == -1)
return Integer.MAX_VALUE;
int sign = (a > 0) ^ (b > 0) ? -1 : 1;
if (a > 0) a = -a;
if (b > 0) b = -b;
int res = 0;
while (a <= b){
a -= b;
res ++;
}
return sign * res;
}
*/
// 优化:尝试每次减去除数的倍数
// 时间复杂度:O(logn * logn), n是最大值2147483547 --> 10^10
/*
public int divide3(int a, int b){
// 32位最大值:2^31 - 1 = 2147483647
// 32位最小值:-2^31 = -2147483648
if(a == Integer.MIN_VALUE && b == -1)
return Integer.MAX_VALUE;
int sign = (a > 0) ^ (b > 0) ? -1 : 1;
if (a > 0) a = -a;
if (b > 0) b = -b;
int res = 0;
while (a <= b){
int value = b;
int k = 1;
// 0xc0000000是十进制-2^30的十六进制的表示
// 判断value >= 0xc0000000的原因:保证value + value不会溢出
// 可以这样判断的原因是:0xc0000000是最小值-2^31的一半,
// 而a的值不可能比-2^31还要小,所以value不可能比0xc0000000小
while (value >= 0xc0000000 && a <= value + value){
value += value;
k += k;
}
a -= value;
res += k;
}
return sign * res;
}
*/
// 时间复杂度:O(1)
// 位运算,每次从最大位数开始尝试,31位、30位...
public int divide(int a, int b){
// 32位最大值:2^31 - 1 = 2147483647
// 32位最小值:-2^31 = -2147483648
if(a == Integer.MIN_VALUE && b == -1)
return Integer.MAX_VALUE;
int sign = (a > 0) ^ (b > 0) ? -1 : 1;
a = Math.abs(a);
b = Math.abs(b);
int res = 0;
for(int i=31; i>=0; i--){
/*
首先,右移不会产生越界
其次,无符号右移的目的是:将-2147483648 看成 2147483648
注意:这里不能是(a >>> i) >= b而应该是(a >>> i) - b >=0
为了避免b = -2147483648, (a >>> i) >= b永远为true,但是(a >>> i) - b >=0 为false.
*/
if((a >>> i) - b >= 0){
a -= (b << i);
if(res > Integer.MAX_VALUE - (1 << i)){
return Integer.MIN_VALUE;
}
res += (1 << i);
}
}
return sign == 1 ? res : -res;
}
}