每日一题 - 剑指 Offer 65. 不用加减乘除做加法

题目信息

  • 时间: 2019-07-07

  • 题目链接:Leetcode

  • tag: 位运算 限制运算符号

  • 难易程度:中等

  • 题目描述:

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

示例1:

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

注意

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

解题思路

本题难点

求和不使用 “+”、“-”、“*”、“/” 四则运算符号。

具体思路

位运算

设两数字的二进制形式 a,b ,其求和 s=a+b ,a(i) 代表 a 的二进制第 i 位,则分为以下四种情况:

a(i) b(i) 无进位和n(i) 进位和c(i)
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1

无进位和异或运算 规律相同

进位与运算 规律相同(并需左移一位)

即可将 s = a+b 转化为: s = 非进位和 n + 进位 c

循环求 n和 c ,直至进位 c=0;此时 s=n,返回 n即可。

提示

代码

class Solution {
    public int add(int a, int b) {
        int c = 0;
        while(b != 0){
            c = (a & b) << 1;
            a ^= b;
            b = c;
        }
        return a;
    }
}

复杂度分析:

  • 时间复杂度 O(1) : 最差情况下(例如 a= 0x7fffffff , b=1 时),需循环 31 次,使用 O(1) 时间;每轮中的常数次位操作使用 O(1) 时间。
  • 空间复杂度 O(1) : 使用常数大小的额外空间。

其他优秀解答

解题思路

递归法,把a+b转换成非进位和+进位,由于不能用加法,因此要一直转换直到第二个加数变成0。

代码

class Solution {
    public int add(int a, int b) {
        if (b == 0) {
            return a;
        }
        // 转换成非进位和 + 进位
        return add(a ^ b, (a & b) << 1);
    }
}
posted @ 2020-07-18 00:31  小锵同学、  阅读(90)  评论(0编辑  收藏  举报