[LeetCode] 367. Valid Perfect Square 檢驗完全平方數


 

Given a positive integer num, write a function which returns True if num is a perfect square else False.

Note: Do not use any built-in library function such as sqrt.

Example 1:

Input: 16
Returns: True

Example 2:

Input: 14
Returns: False

Credits:
Special thanks to @elmirap for adding this problem and creating all test cases.

 

這道題給了我們一個數,讓我們判斷其是否為完全平方數,那么顯而易見的是,肯定不能使用 brute force,這樣太不高效了,那么最小是能以指數的速度來縮小范圍,那么我最先想出的方法是這樣的,比如一個數字 49,我們先對其除以2,得到 24,發現 24 的平方大於 49,那么再對 24 除以2,得到 12,發現 12 的平方還是大於 49,再對 12 除以2,得到6,發現6的平方小於 49,於是遍歷6到 12 中的所有數,看有沒有平方等於 49 的,有就返回 true,沒有就返回 false,參見代碼如下:

 

解法一:

class Solution {
public:
    bool isPerfectSquare(int num) {
        if (num == 1) return true;
        long x = num / 2, t = x * x;
        while (t > num) {
            x /= 2;
            t = x * x;
        }
        for (int i = x; i <= 2 * x; ++i) {
            if (i * i == num) return true;
        }
        return false;
    }
}; 

 

下面這種方法也比較高效,從1搜索到 sqrt(num),看有沒有平方正好等於 num 的數:

 

解法二:

class Solution {
public:
    bool isPerfectSquare(int num) {
        for (int i = 1; i <= num / i; ++i) {
            if (i * i == num) return true;
        }
        return false;
    }
}; 

 

我們也可以使用二分查找法來做,要查找的數為 mid*mid,參見代碼如下:

 

解法三:

class Solution {
public:
    bool isPerfectSquare(int num) {
        long left = 0, right = num;
        while (left <= right) {
            long mid = left + (right - left) / 2, t = mid * mid;
            if (t == num) return true;
            if (t < num) left = mid + 1;
            else right = mid - 1;
        }
        return false;
    }
};

 

下面這種方法就是純數學解法了,利用到了這樣一條性質,完全平方數是一系列奇數之和,例如:

1 = 1
4 = 1 + 3
9 = 1 + 3 + 5
16 = 1 + 3 + 5 + 7
25 = 1 + 3 + 5 + 7 + 9
36 = 1 + 3 + 5 + 7 + 9 + 11
....
1+3+...+(2n-1) = (2n-1 + 1)n/2 = n*n

這里就不做證明了,我也不會證明,知道了這條性質,就可以利用其來解題了,時間復雜度為 O(sqrt(n))。

 

解法四:

class Solution {
public:
    bool isPerfectSquare(int num) {
        int i = 1;
        while (num > 0) {
            num -= i;
            i += 2;
        }
        return num == 0;
    }
};

 

下面這種方法是第一種方法的類似方法,更加精簡了,時間復雜度為 O(lgn):

 

解法五:

class Solution {
public:
    bool isPerfectSquare(int num) {
        long x = num;
        while (x * x > num) {
            x = (x + num / x) / 2;
        }
        return x * x == num;
    }
};

 

這道題其實還有 O(1) 的解法,這你敢信?簡直太喪心病狂了,詳情請參見論壇上的這個帖子

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/367

 

類似題目:

Sqrt(x)

 

參考資料:

https://leetcode.com/problems/valid-perfect-square/

https://leetcode.com/problems/valid-perfect-square/discuss/83872/O(1)-time-c%2B%2B-solution-inspired-by-Q_rsqrt

https://leetcode.com/problems/valid-perfect-square/discuss/83874/A-square-number-is-1%2B3%2B5%2B7%2B...-JAVA-code

https://leetcode.com/problems/valid-perfect-square/discuss/83902/Java-Three-Solutions-135..-SequenceBinary-SearchNewton

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM