剑指Offer:[第21天 位运算(简单)]--->不用加减乘除做加法


一、题目描述

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

示例:

输入: a = 1, b = 1
输出: 2

提示:

a, b 均可能是负数或 0
结果不会溢出 32 位整数


二、思路分析

注:思路分析中的一些内容和图片参考自力扣各位前辈的题解,感谢他们的无私奉献

思路

设两数字的二进制形式 a a a b b b,其求和 s = a + b s = a + b s=a+b a ( i ) a(i) a(i) b ( i ) b(i) b(i) 分别代表 a a a b b b 的二进制第 i i i 位,则分为以下四种情况:
在这里插入图片描述
观察发现,无进位和与异或运算规律相同,进位和与运算规律相同(并需左移一位)。因此,无进位和 n n n 与进位 c c c 的计算公式如下:
在这里插入图片描述
(和 s s s) =(非进位和 n n n) + (进位 c c c)。即可将 s = a + b s = a + b s=a+b 转化为:
s = a + b ⇒ s = n + c s = a + b \Rightarrow s = n + c s=a+bs=n+c
循环求 n n n c c c,直至进位 c = 0 c = 0 c=0。此时 s = n s = n s=n,返回 n n n 即可。
在这里插入图片描述
问题: 若数字 a a a b b b 中有负数,则变成了减法,如何处理?
在计算机系统中,数值一律用补码来表示和存储。补码的优势:加法、减法可以统一处理(CPU只有加法器)。因此,以上方法 同时适用于正数和负数的加法。关于补码的相关知识可以参考博客:数据类型----1.3节:补码
案例分析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
复杂度分析:
时间复杂度 O ( 1 ) \rm{O(1)} O(1):最差情况下(例如a=0x7fffffffb=1时),需循环32次,使用O(1)时间,每轮中的常数次位操作使用O(1)时间。
空间复杂度 O ( 1 ) \rm{O(1)} O(1):使用常数大小的额外空间。


三、整体代码

整体代码如下

int add(int a, int b){
    /*因为s=a+b不允许用+号,所以求出异或部分n、进位部分c后依然不能用s=n+c,
    只能对s=n+c继续进行求异或、求进位,直到进位为0,此时s=n  
    */
    while(b != 0){             //当进位为0时跳出
    	//c语言中int 型做左移运算时,因为有符号位,所以会溢出,必须强制转化成无符号数
        int c = (unsigned int)(a & b) << 1;  //保存进位值,下次循环用
        a ^= b;                //a=非进位和
        b = c;                 //b=进位,如果还有进位,再循环,如果没有,则直接输出没有进位部分即可。
    }

    return a;
}

运行,测试通过
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知初与修一

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

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

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

打赏作者

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

抵扣说明:

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

余额充值