【刷穿 LeetCode】371. 两整数之和 : 使用「位运算」求解的两种方式

简介: 【刷穿 LeetCode】371. 两整数之和 : 使用「位运算」求解的两种方式

网络异常,图片无法展示
|

题目描述


这是 LeetCode 上的 371. 两整数之和 ,难度为 中等


Tag : 「位运算」


给你两个整数 ab ,不使用 运算符 +-,计算并返回两整数之和。


示例 1:


输入:a = 1, b = 2
输出:3
复制代码


示例 2:


输入:a = 2, b = 3
输出:5
复制代码


提示:


  • -1000 <= a, b <= 1000


位运算



一个朴素的做法是使用「位运算」,利用二进制的「逢二进一」和「int 二进制表示长度为 3232」,我们可以从低位往高位进行处理,处理过程中使用变量 tt 记录进位信息。


然后对两数当前位进行分情况讨论:


  • 两个当前位均为 11:此时当前位是什么取决于前一位的进位情况,即有 ans |= (t << i),同时进位 t = 1t=1
  • 两个当前位只有一位是11:此时当前位是什么取决于前一位的进位情况(整理后可统一为ans |= ((1 ^ t) << i)
  • 前一进位若为 11,结合该位为 11,则有当前位为 00,进位不变 t = 1t=1
  • 前一进位若为 00,结合该位为 11,则有当前位为 11,进位不变 t = 0t=0
  • 两个当前位为 00:此时当前位是什么取决于前一位的进位情况,则有 ans |= (t << i),同时进位 t = 0t=0


代码:


class Solution {
    public int getSum(int a, int b) {
        int ans = 0;
        for (int i = 0, t = 0; i < 32; i++) {
            int u1 = (a >> i) & 1, u2 = (b >> i) & 1;
            if (u1 == 1 && u2 == 1) {
                ans |= (t << i);
                t = 1;
            } else if (u1 == 1 || u2 == 1) {
                ans |= ((1 ^ t) << i);
            } else {
                ans |= (t << i);
                t = 0;
            }
        }
        return ans;
    }
}
复制代码


  • 时间复杂度:O(C)O(C)CC 为常数,固定为 3232
  • 空间复杂度:O(1)O(1)


递归



在彻底理解「解法一」后,不难发现「解法一」中本质是分别对两数的当前位进行“拆分”求解。


先计算原始的 aa 的和原始 bb 在不考虑进位的情况下的结果,结果为 a ^ b,然后在此基础上,考虑将进位累加进来,累加操作可以递归使用 getSum 来处理。


问题转化为如何求得 aabb 的进位值。


不难发现,当且仅当 aabb 的当前位均为 11,该位才存在进位,同时进位回应用到当前位的下一位(左边的一边,高一位),因此最终的进位结果为 (a & b) << 1


因此,递归调用 getSum(a ^ b, (a & b) << 1) 我们可以得到最终答案。


最后还要考虑,该拆分过程何时结束。


由于在进位结果 (a & b) << 1 中存在左移操作,因此最多执行 3232 次的递归操作之后,该值会变为 00,而 00 与任何值 xx 相加结果均为 xx


代码:


class Solution {
    public int getSum(int a, int b) {
        return b == 0 ? a : getSum(a ^ b, (a & b) << 1);
    }
}
复制代码


  • 时间复杂度:令 CC 为常数,固定为 3232,最多执行 CC 次的 (a & b) << 1,递归过程结束。复杂度为 O(C)O(C)
  • 空间复杂度:O(1)O(1)


最后



这是我们「刷穿 LeetCode」系列文章的第 No.371 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。


在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour…


在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

相关文章
|
2月前
|
存储
LeetCode整数反转
解决LeetCode上的整数反转问题的几种方法,包括错误的方法和优化后的解决方案,以及如何避免反转后的整数超出32位有符号整数范围的问题。
39 1
|
4月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
124 2
|
2月前
【LeetCode】整数翻转
【LeetCode】整数翻转
17 1
|
2月前
|
存储 C++
Leetcode第十二题(整数转罗马数字)
LeetCode第12题“整数转罗马数字”的解题方法,包括罗马数字的基本规则和特殊规则,以及如何使用C++实现整数到罗马数字的转换。
19 0
|
2月前
|
C++
Leetcode第十三题(罗马数字转整数)
这篇文章介绍了LeetCode第13题“罗马数字转整数”的解题方法,通过一个C++的类`Solution`中的`romanToInt`函数来实现,该函数使用哈希表和遍历字符串的方法,根据罗马数字的规则将输入的罗马数字字符串转换为对应的整数值。
54 0
|
2月前
|
算法 C++
Leetcode第八题(字符串转换整数(atoi))
这篇文章介绍了LeetCode上第8题“字符串转换整数(atoi)”的解题思路和C++的实现方法,包括处理前导空格、正负号、连续数字字符以及整数溢出的情况。
20 0
|
4月前
|
算法
LeetCode第12题目整数转罗马数字
该文章介绍了 LeetCode 第 12 题整数转罗马数字的解法,通过使用 TreeMap 按照整数从大到小排序,先使用大的罗马数字表示整数,再用小的,核心是先表示完大的罗马数字,想通此点该题较简单。
LeetCode第12题目整数转罗马数字
|
4月前
|
算法
LeetCode第8题字符串转换整数 (atoi)
该文章介绍了 LeetCode 第 8 题字符串转换整数 (atoi)的解法,需要对字符串进行格式解析与校验,去除前导空格和处理正负号,通过从高位到低位的计算方式将字符串转换为整数,并处理越界情况。同时总结了这几道题都需要对数字的表示有理解。
LeetCode第8题字符串转换整数 (atoi)
|
4月前
|
算法
LeetCode第7题整数反转
该文章介绍了 LeetCode 第 7 题整数反转的解法,通过除 10 取模和乘 10 累加的方式实现整数反转,同时注意边界情况的判断,并总结了通过举例推算发现规律的解题思路。
LeetCode第7题整数反转
|
4月前
|
算法
LeetCode第13题目罗马数字转整数
该文章介绍了 LeetCode 第 13 题罗马数字转整数的解法,通过从大到小解析罗马数字,根据罗马数字的特点,按照从大到小的顺序匹配罗马数字和整数的关系,从而解决该问题,同时强调要注意观察题目考查的知识点特征。