Swift 解法详解:LeetCode 367《有效的完全平方数》


文章目录

摘要

判断一个数是不是完全平方数,看似简单,但题目要求我们不能用 sqrt 这样的现成函数。也就是说,我们得自己想办法去模拟"开平方"的过程。这种题很有意思,不光能训练我们对二分查找的掌握,还能让我们思考数字在计算机里的表现方式。

描述

题目给了一个正整数 num,问它是不是某个整数的平方。

  • 如果是,返回 true
  • 如果不是,返回 false

完全平方数 :就是能写成 a * a 形式的数,比如:

  • 16 = 4 * 4
  • 9 = 3 * 3
  • 25 = 5 * 5

但像 14 就不行,它介于 3² 和 4² 之间,平方根不是整数。

输入输出例子:

txt 复制代码
输入:num = 16
输出:true

输入:num = 14
输出:false

题解答案

一个直接的办法是从 1 开始,一个个平方,看是不是等于 num。但这样效率太低,尤其是 num 最大能到 2^31 - 1(20 多亿)。

更高效的方式是用 二分查找

  1. 搜索范围是 [1, num]

  2. 每次取中点 mid,计算 mid * mid

    • 如果等于 num,那就是完全平方数。
    • 如果比 num 大,说明平方根在左半边。
    • 如果比 num 小,说明平方根在右半边。
  3. 一直缩小范围,直到找到答案。

题解代码分析

下面是 Swift 的实现:

swift 复制代码
import Foundation

class Solution {
    func isPerfectSquare(_ num: Int) -> Bool {
        if num < 2 {
            return true
        }
        
        var left = 1
        var right = num / 2  // 平方根不可能超过 num/2 (除非 num=1)
        
        while left <= right {
            let mid = left + (right - left) / 2
            let square = mid * mid
            
            if square == num {
                return true
            } else if square < num {
                left = mid + 1
            } else {
                right = mid - 1
            }
        }
        
        return false
    }
}

// MARK: - Demo 演示
let solution = Solution()
print(solution.isPerfectSquare(16))  // true
print(solution.isPerfectSquare(14))  // false
print(solution.isPerfectSquare(1))   // true
print(solution.isPerfectSquare(808201)) // true (因为 899 * 899 = 808201)

代码拆解

  1. 特殊情况 :如果 num < 2,比如 0 或 1,直接返回 true

  2. 二分边界

    • 左边界 left = 1
    • 右边界 right = num / 2,因为平方根不会超过 num/2(除了 num=1)。
  3. 二分逻辑

    • 每次计算 mid * mid
    • 如果等于 num,直接返回 true
    • 如果小于 num,收缩到右区间。
    • 如果大于 num,收缩到左区间。
  4. 返回结果 :没找到说明不是完全平方数,返回 false

示例测试及结果

运行上面 Demo,得到结果:

txt 复制代码
true
false
true
true

更丰富的测试:

swift 复制代码
print(solution.isPerfectSquare(25)) // true
print(solution.isPerfectSquare(26)) // false
print(solution.isPerfectSquare(100)) // true
print(solution.isPerfectSquare(2147395600)) // true (46340 * 46340)
print(solution.isPerfectSquare(2147483647)) // false (最大 int,不是平方数)

时间复杂度

  • 二分查找每次把搜索区间减半,最多执行 O(log n) 次比较。
  • 每次计算 mid * mid 是 O(1)。
  • 所以整体复杂度是 O(log n)

空间复杂度

  • 只用了常数级别的变量 leftrightmidsquare
  • 空间复杂度是 O(1)

总结

这道题其实就是把"数学直觉"转化成"计算机算法"的过程:

  • 我们人眼可以轻松判断一个数是不是完全平方数,比如看到 16 就知道是 4²。
  • 但计算机不能直接用 sqrt,就需要用二分查找模拟"开方"的过程。

实际应用场景里,这种"判断平方数"的逻辑可能用在:

  • 图像处理里判断像素矩阵是不是正方形。
  • 数字加密里验证一些平方相关的条件。
  • 游戏开发中做网格计算,判断一个范围是不是可以正好铺满。
相关推荐
杜子不疼.17 小时前
PyPTO:面向NPU的高效并行张量编程范式
开发语言
lly20240617 小时前
C# 结构体(Struct)
开发语言
YMWM_17 小时前
python3继承使用
开发语言·python
Once_day18 小时前
C++之《程序员自我修养》读书总结(1)
c语言·开发语言·c++·程序员自我修养
喜欢喝果茶.18 小时前
QOverload<参数列表>::of(&函数名)信号槽
开发语言·qt
亓才孓18 小时前
[Class类的应用]反射的理解
开发语言·python
努力学编程呀(๑•ี_เ•ี๑)18 小时前
【在 IntelliJ IDEA 中切换项目 JDK 版本】
java·开发语言·intellij-idea
island131418 小时前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构任务的 Stream 调度机制
开发语言·人工智能·深度学习·神经网络
坚持就完事了18 小时前
Java中的集合
java·开发语言