解题思路
不要抖机灵!不要抖机灵!不要抖机灵!
- 重要的事情说三遍
- 先找,题源:《程序员面试金典(第六版)》
- 然后翻评论区 @joswxe 站在巨人的肩膀上
- 核心思想就是倍增
- 乘法的本质是:加法
- 除法的本质是:减法
- 每次只需要把
乘数
or除数
按照二进制拆开考虑 - 即可优化运算为:\(O(log(b))\)
- 我们可以拼接出如下代码
优化点
- 使用静态数组,不涉及
vector
的API
- 常数
-1
用十六进制码0xFFFFFFFF
表示,完全不使用任何-
号 - 额外实现了取相反数的运算,(
from
《程序员面试金典(第六版)》)
代码
class Operations {
public:
int tmp[32], count[32];
int tmpSize, countSize;
Operations() {
}
int negative(int a) {
int neg = 0;
int newSign = a < 0 ? 1 : 0xFFFFFFFF;
long delta = newSign;
while (a != 0) {
bool differentSigns = (a + delta > 0) != (a > 0);
if (a + delta != 0 && differentSigns) { // 如果 delta 过大,则重置
delta = newSign;
}
neg += delta;
a += delta;
delta += delta; // 将 delta 增大一倍
}
return neg;
}
int minus(int a, int b) {
return a + negative(b);
}
int multiply(int a, int b) {
if (a == 0 || b == 0) return 0;
if (a == 1) return b;
if (b == 1) return a;
if (a == 0xFFFFFFFF) return negative(b);
if (b == 0xFFFFFFFF) return negative(a);
int cnt = 0;
if (a < 0) cnt = cnt + 1, a = negative(a);
if (b < 0) cnt = cnt + 1, b = negative(b);
if (a > b) swap(a, b);
tmpSize=countSize=0;
long t = b;
int k = 1;
while (t <= INT_MAX) tmp[tmpSize++]=t, count[countSize++]=k, t = t + t, k = k + k;
int res = 0;
for (int i = minus(tmpSize, 1); i >= 0; i = minus(i, 1)) {
while (a >= count[i]) a = minus(a, count[i]), res = res + tmp[i];
}
if (cnt == 1) return negative(res);
return res;
}
int divide(int a, int b) {
if (a == 0 || b == 0) return 0;
if (b == INT_MAX || b == INT_MIN) return 0;
if (b == 1) return a;
if (b == 0xFFFFFFFF) return negative(a);
int cnt = 0;
if (a < 0) cnt = cnt + 1, a = negative(a);
if (b < 0) cnt = cnt + 1, b = negative(b);
if (a < b) return 0;
tmpSize=countSize=0;
long t = b;
int k = 1;
while (a >= t) tmp[tmpSize++]=t, count[countSize++]=k, t = t + t, k = k + k;
int res = 0;
for (int i = minus(tmpSize, 1); i >= 0; i = minus(i, 1)) {
while (a >= tmp[i]) a = minus(a, tmp[i]), res = res + count[i];
}
if (cnt == 1) return negative(res);
return res;
}
};