Swift 解法详解:LeetCode 371《两整数之和》


文章目录

摘要

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

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

描述

题目要求:

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

示例 1

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

示例 2

txt 复制代码
输入: 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 实现:

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 代码:

txt 复制代码
输入: (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 的加法实现。
  • 高性能计算场景里的快速运算。
  • 特定场景下避免溢出的操作。

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

相关推荐
yaoxin5211234 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
凡人叶枫4 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
学逆向的5 小时前
C++纯虚函数
开发语言·c++·网络安全
程序员二叉5 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc
程序员二叉5 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
凡人叶枫6 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++
Qt程序员6 小时前
掌握 Linux 内核调度:从原理到实现(进程篇)
java·开发语言
code bean6 小时前
【LangChain】检索器完全指南:从向量检索到生产级 RAG 架构
java·开发语言·微服务
LabVIEW开发7 小时前
LabVIEW + MATLAB 混合编程:爆炸场测试数据精准采集方案
开发语言·matlab·labview
嵌入式协会20240727 小时前
(已解决)MinIO python 获取预签名出现forbidden、errornetwork等错误
java·开发语言·python