【位运算】不用加减乘除做加法

文章目录

在这里插入图片描述

题目

时间限制:1s
空间限制:256MB

题目描述:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

数据范围:两个数都满足 -10 ≤ n ≤ 1000

进阶:空间复杂度 O(1),时间复杂度 O(1)

示例1

输入:1,2
输出:3

示例2

输入:0,0
输出:0

分析

可以使用位运算符 ^(XOR)、&(AND)和 <<(左移)来实现加法,是因为这些操作能够有效地模拟二进制加法的步骤。让我们一步步分析其原理:

  1. 异或运算 ^

    异或运算用于计算不带进位的部分和。其运算规则如下:

    • 0 ^ 0 = 0
    • 0 ^ 1 = 1
    • 1 ^ 0 = 1
    • 1 ^ 1 = 0

    可以看到,异或运算的结果与普通加法的结果类似,只不过它没有处理进位。对于每一位:

    • 如果两位不同,则结果为 1(相当于 1+0 或 0+1 的情况)。
    • 如果两位相同,则结果为 0(相当于 0+0 或 1+1(不带进位)的情况)。

    我们可以利用这个特性模拟(没有进位的)加法运算。

  2. 与运算 &

    与运算用于计算进位。其运算规则如下:

    • 0 & 0 = 0
    • 0 & 1 = 0
    • 1 & 0 = 0
    • 1 & 1 = 1

    可以看到,只有在两个位都是 1 时,结果才是 1,这正是进位的条件。每一位的与运算结果实际上代表了该位与其相邻高一位之间的进位。

  3. 左移运算 <<

    左移运算用于将进位向左移动一位。因为进位应当加到更高一位的相应位置上:

    例如,对于二进制数 1 & 1 产生的进位,其应加到更高一位上,即通过左移一位实现这一目的。

  4. 综合以上操作

    通过重复进行上述三个操作(异或、与、左移),我们可以将不带进位的和和进位合并,最终得到完整的加法结果。具体步骤如下:

    1. 计算不带进位的和sum = a ^ b
    2. 计算进位carry = (a & b) << 1
    3. 将不带进位的和赋给 a,将进位赋给 ba = sum; b = carry
    4. 重复上述步骤,直到进位为 0

    每次迭代中,ab 会逐渐靠近最终的和,直到 b(进位)变为 0。

  5. 处理负数

    由于计算机中的整数使用补码表示,负数在二进制表示中会自动处理进位。因此,上述算法同样适用于负数加法。补码的特性使得负数的加法与正数的加法在位运算层面上是一致的,不需要额外的处理。

题解

class Solution
{
public:
    int Add(int num1, int num2)
    {
        while (num2 != 0)
        {
            int sum = num1 ^ num2;
            num2 = (num1 & num2) << 1;
            num1 = sum;
        }
        return num1;
    }
};

空间复杂度:只额外开了一个 int 型的空间,故空间复杂度为 O(1)。

时间复杂度:时间复杂度取决于数字的位数,如果只是处理 int 或 long long int 这种限制了数字位数的类型,时间复杂度为 O(1);如果处理的数字为无限大,时间复杂度为 O(log n);在大多数情况下我们认为该程序的时间复杂度为 O(1)。


END
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

字节连结

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值