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,就需要用二分查找模拟"开方"的过程。

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

  • 图像处理里判断像素矩阵是不是正方形。
  • 数字加密里验证一些平方相关的条件。
  • 游戏开发中做网格计算,判断一个范围是不是可以正好铺满。
相关推荐
Morpheon20 小时前
Intro to R Programming - Lesson 4 (Graphs)
开发语言·r语言
代码AI弗森20 小时前
使用 JavaScript 构建 RAG(检索增强生成)库:原理与实现
开发语言·javascript·ecmascript
Tipriest_21 小时前
C++ 中 ::(作用域解析运算符)的用途
开发语言·c++·作用域解析
Swift社区21 小时前
Java 常见异常系列:ClassNotFoundException 类找不到
java·开发语言
Tipriest_21 小时前
求一个整数x的平方根到指定精度[C++][Python]
开发语言·c++·python
蓝倾9761 天前
淘宝/天猫店铺商品搜索API(taobao.item_search_shop)返回值详解
android·大数据·开发语言·python·开放api接口·淘宝开放平台
John_ToDebug1 天前
从源码看浏览器弹窗消息机制:SetDefaultView 的创建、消息转发与本地/在线页通用实践
开发语言·c++·chrome
圣保罗的大教堂1 天前
leetcode 3446. 按对角线进行矩阵排序 中等
leetcode
菌王1 天前
EXCEL 2 word 的一些案例。excel通过一些策略将内容写入word中。
开发语言·c#
励志不掉头发的内向程序员1 天前
STL库——list(类模拟实现)
开发语言·c++·学习