剑指Offer | 整数运算01(简单)

剑指 Offer II 001. 整数除法


题目描述:

给定两个整数 ab ,求它们的除法的商 a/b ,要求不得使用乘号 '*'、除号 '/' 以及求余符号 '%'


示例:

输入:a = 15, b = 2
输出:7
解释:15/2 = truncate(7.5) = 7

限制:

1.除法的结果向零取整
2.假设我们的环境只能存储 32 位有符号整数,如果除法结果溢出,则返回 2^31 − 1

思路:用减法代替除法,并用位运算来代替算术运算

class Solution {
public:
    int divide(int a, int b) {
        // 确定边界
        if(a == INT_MIN && b == -1) return INT_MAX;

        // 记录符号
        int sign = (a>0) ^ (b>0) ? -1 : 1;
        
        //取绝对值
        unsigned int ua = abs(a);
        unsigned int ub = abs(b);
        unsigned int res = 0;

        // 进行减法运算
        for(int i = 31; i >= 0; i--){
        	// (ua>>i) >= ub 等同于 ua >= (ub<<i)
            // 这样判断是为了避免溢出
            if((ua>>i) >= ub){
                ua = ua - (ub << i);
                res += (1<<i);
            }
        }

        //返回最终结果
        return sign == 1 ? res : -res;
    }

};


剑指 Offer II 002. 二进制加法


题目描述:

给定两个 01 字符串 ab ,请计算它们的和,并以二进制字符串的形式输出。

输入为 非空 字符串且只包含数字 10


示例

输入: a = "11", b = "10"
输出: "101"

限制:

1.每个字符串仅由字符 '0' 或 '1' 组成。
2.1 <= a.length, b.length <= 10^4
3.字符串如果不是 "0" ,就都不含前导零。

思路:用进位思想进行加法运算

class Solution {
public:
    string addBinary(string a, string b) {
        // 取二者最长者的长度
        int n = max(a.size(), b.size());
        int flag = 0;
        string res;

        // 反转a,b
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        a.resize(n);
        b.resize(n);

        // 执行二进制加法
        for (int i = 0; i < n; i++) {
            int temp = a[i] + b[i] - 2 * '0';
            // 调整temp
            if(temp < 0) {
                temp += '0';
            }
            // 两个1
            else if (temp > 1) {
                res += flag ? '1' : '0';
                flag = 1;
            }
            // 一个0一个1
            else if (temp == 1) {
                if (flag == 1) {
                    res += '0';
                    flag = 1;
                }
                else {
                    res += '1';
                    flag = 0;
                }
            }
            // 两个0
            else {
                res += flag ? '1' : '0';
                flag = 0;
            }
        }

        // 判断最后一位
        if (flag == 1) {
            res += '1';
        }

        //反转后输出
        reverse(res.begin(), res.end());
        return res;
    }
};


剑指 Offer II 003. 前 n 个数字二进制中 1 的个数


题目描述:

给定一个非负整数 n ,请计算 0n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。


示例

输入: n = 2
输出: [0,1,1]
解释: 
0 --> 0
1 --> 1
2 --> 10

限制 :

1.0 <= n <= 105

题解思路:利用 n & (n-1) 能用来计算n中1的个数 的特性 解决本题目


思路:对于0-n中的每一个数i,都用 i&(i-1) 的公式迭代计算i中1的个数

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> res;
        for(int i = 0; i <= n; i++){
            int j = i;
            int cnt = 0;
            while(j != 0) {
                j = j & (j-1);
                cnt++;
            }
            res.push_back(cnt);
        }
        return res;
    }
};

思路:将上述 i&(i-1) 的公式用位运算来表示。

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> ret(n + 1, 0);
        for (int i = 1; i <= n; ++i) {
            ret[i] = ret[i & (i - 1)] + 1;
        }
        return ret;
    }
};

posted @ 2021-09-24 23:42  不是勇士  阅读(104)  评论(0)    收藏  举报