LeetCode —— 367. 有效的完全平方数

105 阅读2分钟

启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

该题是数组二分查找题型第五题。

题目来源

367. 有效的完全平方数(LeetCode)

题目描述(简单

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。

进阶:不要 使用任何内置的库函数,如  sqrt 。

示例1

输入: num = 16
输出: true

示例2

输入: num = 14
输出: false

提示

  • 1<=num<=23111 <= num <= 2^{31} - 1

题目解析

基础方法直接使用内置函数即可,但进阶要求中要求 不能使用任何内置的库函数 ,所以 LeetCode —— 69. x 的平方根 - 掘金 中的袖珍计算器算法也只能算基础方法的一种。

二分查找

当我们以二分查找的思维去看待这题时,你会发现该题默认满足有序且无重复的条件,即一个长度为 num ,从 1 开始到 num 结束且递增无重复的数组。在之前的几题中我习惯使用 Math.floor() 该方法避免右区间或中位值 mid 赋值为浮点数,其实可以采用 parseInt() 函数替代。

代码(进阶)

/**
 * @param {number} num
 * @return {boolean}
 */
var isPerfectSquare = function(num) {
    let left = 1, right = parseInt(num / 2) + 1
    while (right >= left) {
        let mid = parseInt((left + right) / 2)
        if(mid * mid > num){
            right = mid - 1
        }else if (mid * mid < num) {
            left = mid + 1
        }else {
            return true
        }
    }
    return false
};

如图:

image.png

内置函数

该方法十分简单主要根据完全平方根的特性,判断 num 的平方根是否为整数即可。

代码

/**
 * @param {number} num
 * @return {boolean}
 */
var isPerfectSquare = function(num) {
    return Math.sqrt(num) === parseInt(Math.sqrt(num))
};

如图:

image.png

暴力

如果 num 是完全平方数,那么一定存在正整数 square 满足 square * square = num 。于是我们朴素的遍历寻找是否存在 sqaure 满足该条件。当然在遍历中出现 square * square > num 的情况时,那么代表 square 不存在,直接返回 false 即可。

代码

/**
 * @param {number} num
 * @return {boolean}
 */
var isPerfectSquare = function(num) {
    let square = 1
    while (square * square <= num) {
        if (square * square === num){
            return true
        }
        square++
    }
    return false
};

如图:

image.png

等差数列求和

经过 LeetCode —— 69. x 的平方根 - 掘金 和该题,做梦时,我居然回忆到高中讲等差数列时,将 iϵ[1,...,n]i \epsilon [1,...,n]n>=1n >= 1 ),第 i 项为 2×i12 \times i - 1 的等差数列求和后,必定为完全平方数。

因此该方法是将 num 减去等差数列的 第 i 项( iϵ[1,...,n]i \epsilon [1, ... , n]n>=1n >= 1 ), i1 开始)。如果 num 出现 0 ,则 num 是完全平方数,反之为不完全平方数。

代码

/**
 * @param {number} num
 * @return {boolean}
 */
var isPerfectSquare = function(num) {
    for (let i = 1;i <= num;i+=2){
        num -= i
        if (num === 0){
            return true
        }
    }
    return false
};

image.png

执行用时和内存消耗仅供参考,大家可以多提交几次。如有更好的想法,欢迎大家提出。