https://leetcode.cn/problems/divide-two-integers/

法一:位运算

  • 加法
      1. ^ 无进位相加
      1. & << 1 进位相加
    • 将第一步和第二步加起来
    • 例子1:image.png
    • 例子2:
      • image.png
        1. public static int add(int a, int b) {
        2. int sum = a;
        3. while (b != 0) {
        4. sum = a ^ b;
        5. b = (a & b) << 1;
        6. a = sum;
        7. }
        8. return sum;
        9. }
  • 乘法
    • 流程
      • image.png
      • 原始的a ,b不变
        • a << 0 , b >> 0
        • a << 1, b >> 1
        • a << 2, b>>2
          1. public static int multi(int a, int b) {
          2. int res = 0;
          3. while (b != 0) {
          4. if ((b & 1) != 0) {
          5. res = add(res, a);
          6. }
          7. a <<= 1;
          8. b >>>= 1;
          9. }
          10. return res;
          11. }

除法: 如果a是系统最小, b不是系统最小,怎么算? 1.先把a+1 ,然后去除b ——> 得到值A

  1. 2. a - (A * b) = B
  2. 3. B / b + A

除法:

  • 先把数都转成正的,来除比较稳
  • 所以除的流程是什么呢?
    • 比如a/b
    • 准备一个变量
    • 先让 b往左移动x位,直到不能再移(最接近a) 记作T, 然后在上面那个变量对象x位置写上1
    • 然后 a’ = a - T
    • 然后再让b往左移动去够a’ , 继续上面那个流程
    • image.png
  • 为啥是这个流程呢?看下面两个图
    • image.png
    • image.png ```java public static int minus(int a, int b) { return add(a, negNum(b)); } // 求相反数 private static int negNum(int n) { return add(~n, 1); }

public static int div(int a, int b) { int x = a < 0 ? negNum(a) : a; int y = b < 0 ? negNum(b) : b; int res = 0; for (int i = 31; i > -1; i = minus(i, 1)) { if (x >> i >= y) { res |= (1 << i); x = minus(x, y << i); } } return (a < 0) ^ (b < 0) ? negNum(res) : res; }

public static int divide(int dividend, int divisor) { if (divisor == Integer.MIN_VALUE) { return dividend == Integer.MIN_VALUE ? 1 : 0; } // 除数不是系统最小 if (dividend == Integer.MIN_VALUE) { if (divisor == -1) { return Integer.MAX_VALUE; } int res = div(add(dividend, 1), divisor); return add(res, div(minus(dividend, multi(res, divisor)), divisor)); } // 两个都不是系统最小 return div(dividend, divisor); }

  1. - 总代码
  2. ```java
  3. public static int add(int a, int b) {
  4. int sum = a;
  5. while (b != 0) {
  6. sum = a ^ b;
  7. b = (a & b) << 1;
  8. a = sum;
  9. }
  10. return sum;
  11. }
  12. public static int multi(int a, int b) {
  13. int res = 0;
  14. while (b != 0) {
  15. if ((b & 1) != 0) {
  16. res = add(res, a);
  17. }
  18. a <<= 1;
  19. b >>>= 1;
  20. }
  21. return res;
  22. }
  23. public static int minus(int a, int b) {
  24. return add(a, negNum(b));
  25. }
  26. private static int negNum(int n) {
  27. return add(~n, 1);
  28. }
  29. public static int div(int a, int b) {
  30. int x = a < 0 ? negNum(a) : a;
  31. int y = b < 0 ? negNum(b) : b;
  32. int res = 0;
  33. for (int i = 31; i > -1; i = minus(i, 1)) {
  34. if (x >> i >= y) {
  35. res |= (1 << i);
  36. x = minus(x, y << i);
  37. }
  38. }
  39. return (a < 0) ^ (b < 0) ? negNum(res) : res;
  40. }
  41. public static int divide(int dividend, int divisor) {
  42. if (divisor == Integer.MIN_VALUE) {
  43. return dividend == Integer.MIN_VALUE ? 1 : 0;
  44. }
  45. // 除数不是系统最小
  46. if (dividend == Integer.MIN_VALUE) {
  47. if (divisor == -1) {
  48. return Integer.MAX_VALUE;
  49. }
  50. int res = div(add(dividend, 1), divisor);
  51. return add(res, div(minus(dividend, multi(res, divisor)), divisor));
  52. }
  53. // 两个都不是系统最小
  54. return div(dividend, divisor);
  55. }

法二:递归

  • 每次除数翻倍增加,指数级逼近被除数 ```java public static int divide1(int dividend, int divisor) { if (dividend == 0 ) return 0; if (dividend == Integer.MIN_VALUE && divisor == -1) return Integer.MAX_VALUE; int isNeg = 1; if ((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) {
    1. isNeg = -1;
    } dividend = dividend > 0 ? -dividend : dividend; divisor = divisor > 0 ? -divisor : divisor; return isNeg == -1 ? -div1(dividend, divisor) : div1(dividend, divisor);

}

// a, b都是负数 private static int div1(int a, int b) { if (a >= b) return a > b ? 0 : 1; int count = 1; int res = 0; int tb = b; // 每次除数和结果都翻倍,指数级逼近,比较快 // tb < 0 防止溢出 while (a <= tb && tb < 0) { a -= tb; res += count; tb += tb; count += count; } return res + div1(a, b); }

```