在这里插入图片描述
在这里插入图片描述

摘要

这道题看起来很奇怪:我们要计算两个整数的和,但题目规定 不能用 +- 运算符。听起来像是脑筋急转弯,其实这是一个很经典的“位运算”应用题。通过理解二进制的加法规则,我们完全可以用 位运算 来模拟加法过程。

这类题不仅能训练我们的思维,还能加深对二进制和位操作的理解。在底层开发、嵌入式开发甚至编译器优化里,这些技巧都非常实用。

描述

题目要求:

给你两个整数 ab,不能用 +- 运算符,返回它们的和。

示例 1

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

示例 2

输入: a = 2, b = 3
输出: 5

提示

  • -1000 <= a, b <= 1000

题解答案

要模拟加法,首先回忆一下二进制的运算规则:

  • 不带进位的加法(相当于 XOR 异或):

    • 0 ^ 0 = 0
    • 1 ^ 0 = 1
    • 0 ^ 1 = 1
    • 1 ^ 1 = 0
  • 进位的部分(相当于 AND 与运算,再左移一位):

    • 只有当两位都是 1 时才产生进位。

因此:

  • a ^ b 计算不带进位的和。
  • (a & b) << 1 计算进位。
  • 然后不断迭代,把“和”和“进位”相加,直到进位为 0。

这就是用位运算模拟加法的核心思想。

题解代码分析

下面是 Swift 实现:

import Foundation

class Solution {
    func getSum(_ a: Int, _ b: Int) -> Int {
        var x = a
        var y = b
        
        while y != 0 {
            // 非进位和
            let sum = x ^ y
            // 进位
            let carry = (x & y) << 1
            // 更新 x 和 y
            x = sum
            y = carry
        }
        
        return x
    }
}

// MARK: - Demo 演示
let solution = Solution()
print(solution.getSum(1, 2)) // 输出: 3
print(solution.getSum(2, 3)) // 输出: 5
print(solution.getSum(-2, 3)) // 输出: 1

代码拆解

  1. 初始化变量

    • x 表示当前的和(不带进位)。
    • y 表示进位。
  2. 循环模拟加法

    • sum = x ^ y:这是当前两数的无进位和。
    • carry = (x & y) << 1:这是进位。
    • 更新 x = sumy = carry,继续迭代。
  3. 终止条件

    • 当进位 y = 0 时,说明没有更多进位了,x 就是最终的答案。

示例测试及结果

运行 Demo 代码:

输入: (1, 2)
输出: 3

输入: (2, 3)
输出: 5

输入: (-2, 3)
输出: 1

结果完全符合预期。

这个方法不仅适用于正数,也适用于负数,因为 Swift 的 Int 本质上是补码存储,位运算同样适用。

时间复杂度

  • 每次循环至少会让进位左移一位,所以最多执行 O(32) 次(对于 32 位整数)。
  • 在 Swift 中 Int 是 64 位的,也就是最多执行 O(64) 次。
  • 复杂度可以认为是 O(1)

空间复杂度

  • 只用了常量级的几个变量,空间复杂度是 O(1)

总结

这道题的关键在于理解:

  • a ^ b 负责“加法不带进位”的部分。
  • (a & b) << 1 负责“进位”的部分。
  • 不断迭代直到进位为 0。

这个方法绕开了 +-,用纯粹的位运算模拟了加法的过程。

在实际场景中,位运算往往出现在底层优化或者特殊硬件环境中。比如:

  • 处理器底层 ALU 的加法实现。
  • 高性能计算场景里的快速运算。
  • 特定场景下避免溢出的操作。

掌握这类思路,可以帮助我们更好地理解计算机是如何在底层执行算术运算的。

Logo

加入「COC·上海城市开发者社区」,成就更好的自己!

更多推荐