int left = 1; int right = a; while (left < right) { long mid = left + ((right - left) / 2); // 这边避免溢出 int t = mid * b; if (t > a) { right = mid - 1; } elseif (t < a) { left = mid + 1; } else { return mid; } return left; }
privateintfastAdd(int x, int y){ int ans = 0; int step = 0; while (y > 0) { int l = y & 1; // 记录最后一位 if (l == 1) { // 只有最后一位是1的时候 int t = x << step; // 左移 step ans += t; // 累加 } step += 1; y = y >> 1; // y 右移一位 } return ans; }
所以整体上,只要替换上面的乘法就好了,即int t = fastAdd(mid, b);
但是出现了一个问题,就是在计算int t = fastAdd(mid, b);的时候t会溢出,在整个二分法的过程中,其实我们不关心mid * b的大小,我们想知道它与a的大小关系
int ans = 0; int step = 0; while (y > 0) { int l = y & 1; if (l == 1) { int t = x << step; ans = ans + t; } step = step + 1; y = y >> 1; if (ans > a) { return1; } } int delta = ans - a; if (delta > 0) { return1; } elseif (delta < 0) { return -1; } else { return0; } }
因此上述二分法可以改造为
1 2 3 4 5 6 7 8 9 10 11 12 13 14
int left = 1; int right = a; while (left <= right) { int mid = left + ((right - left) >> 1); int t = fastAdd(mid, b, a); if (t > 0) { right = mid - 1; } elseif (t < 0) { left = mid + 1; } else { return mid; } } return left;
classSolution{ publicintdivide(int a, int b){ if (a == 0) { return0; } if (b == 1) { return a; } if (a == Integer.MIN_VALUE && b == -1) { return Integer.MAX_VALUE; } int flag = 1; if (a < 0) { a = -a; flag = -flag; } if (b < 0) { b = -b; flag = -flag; } if (a < b) { return0; } if (a == b) { return flag; } int left = 1; int right = a; while (left <= right) { int mid = left + ((right - left) >> 1); int t = fastAdd(mid, b, a); if (t > 0) { right = mid - 1; } elseif (t < 0) { left = mid + 1; } else { return mid; } } return flag > 0 ? Math.min(left, right) : -Math.min(left, right); } privateintfastAdd(int x, int y, int a){
int ans = 0; int step = 0; while (y > 0) { int l = y & 1; if (l == 1) { int t = x << step; ans = ans + t; } step = step + 1; y = y >> 1; if (ans > a) { return1; } } int delta = ans - a; if (delta > 0) { return1; } elseif (delta < 0) { return -1; } else { return0; } } }
long a = (long) x; long b = (long) y; if (a == 0) { return0; } if (b == 1) { return (int) a; }
if (a == Integer.MIN_VALUE && b == -1) { return Integer.MAX_VALUE; }
int flag = 1; if (a < 0) { a = -a; flag = -flag; } if (b < 0) { b = -b; flag = -flag; } if (a < b) { return0; } if (a == b) { return flag; }
long left = 1; long right = a; while (left <= right) { long mid = left + ((right - left) >> 1); int t = fastAdd(mid, b, a); if (t > 0) { right = mid - 1; } elseif (t < 0) { left = mid + 1; } else { return flag > 0 ? (int) mid : (int) -mid; } }
return flag > 0 ? (int) Math.min(left, right) : (int) -Math.min(left, right); } privateintfastAdd(long x, long y, long a){
long ans = 0; long step = 0; while (y > 0) { long l = y & 1; if (l == 1) { long t = x << step; ans = ans + t; } step = step + 1; y = y >> 1; if (ans > a) { return1; } } int delta = (int) (ans - a); if (delta > 0) { return1; } elseif (delta < 0) { return -1; } else { return0; } } }