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


    题目链接
    力扣题解链接

    解题思路

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

    • 重要的事情说三遍
    • 先找,题源:《程序员面试金典(第六版)》
    • 然后翻评论区 @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;
        }
    };
    
  • 相关阅读:
    介绍一个成功的 Git 分支模型 Release 分支
    启动安卓模拟器报错 emulator: ERROR: x86_64 emulation currently requires hardware acceleration! CPU acceleration status:HAXM must be updated(version 1.1.1<6.0.1) 解决办法
    AceyOffice教程复制行
    AceyOffice教程设置单元格边框
    Excel生成报表之解决方案合并单元格的用法
    AceyOffice教程报表之解决方案(二)
    Excel生成报表之解决方案插入图片
    AceyOffice教程复制列
    Excel基础知识(一)
    AceyOffice教程报表之解决方案(一)
  • 原文地址:https://www.cnblogs.com/JasonCow/p/15872937.html
Copyright © 2020-2023  润新知