【墨鳌】【只用"加法"和"逻辑运算符",没有毛病】【《程序员面试金典(第六版)》】

题目链接
力扣题解链接

解题思路

不要抖机灵!不要抖机灵!不要抖机灵!

  • 重要的事情说三遍
  • 先找,题源:《程序员面试金典(第六版)》
  • 然后翻评论区 @joswxe 站在巨人的肩膀上
  • 核心思想就是倍增
  • 乘法的本质是:加法
  • 除法的本质是:减法
  • 每次只需要把 乘数 or 除数 按照二进制拆开考虑
  • 即可优化运算为:\(O(log(b))\)
  • 我们可以拼接出如下代码

优化点

  1. 使用静态数组,不涉及 vectorAPI
  2. 常数 -1 用十六进制码 0xFFFFFFFF 表示,完全不使用任何 -
  3. 额外实现了取相反数的运算,(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;
    }
};
posted @ 2022-02-08 21:14  墨鳌  阅读(25)  评论(0编辑  收藏  举报