Time:2019/4/17
Title: sqrt(x)
Difficulty: Easy
Author: 小鹿
題目:sqrt(x)
Implement int sqrt(int x)
.
Compute and return the square root of x, where x is guaranteed to be a non-negative integer.
Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.
實現
int sqrt(int x)
函式。計算並返回 x 的平方根,其中 x 是非負整數。「」
由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。
Example 1:
Input: 4
Output: 2
複製程式碼
Example 2:
Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since
the decimal part is truncated, 2 is returned.
複製程式碼
Solve:
▉ 問題分析
1)根據題目要求,求一個指定樹的平方根,第一要想到的是開平方根是沒有規律可循的,可能想到一個暴力破解法,從 1 開始遍歷,直到滿足
k^2 < x
且(k+1)^2 > x
為止。
- 你可能想到這種方法效率太低,需要從 1 開始,如果 x 很大,豈不是需要遍歷很多?能不能規定一個範圍,在這個範圍中查詢開平方根呢?你會想到,所有數的開平方根得到的值是永遠小於等於自身的(0 是自身),所以 x 的開平方根的值的範圍一定在 0 < k < x 之間。
3)要想在這個區間快速定位找到一個滿足條件的 x ,最高效的方法莫過於二分查詢,但是可能存在小數,這又涉及到二分查詢的四個變體(二分查詢的變形)過程。如果你之前沒有連線過,沒關係,請看我之前記載的一篇文章。
4)雖然我們已經確定瞭解題方法,但是這時候不要著急,想一想這個問題是否滿足二分查詢的四個適用條件?哪四個條件呢?你需要系統學習一下就 ok !
▉ 演算法思路
1)此過程分為兩種情況,負數和正整數,所以要對輸入的 x 進行判斷。
2)然後開始根據二分查詢應該注意的「三個重點」寫出無 bug 的程式碼。
3)對二分查詢進行稍微的變體,因為我們可能查詢的數並不是一個正整數,我們取整數部分就可以了,小數部分省略。
▉ 測試用例
1)輸入 0
2)輸入1
3)輸入負數的 x
4)輸入平方根為正整數的 x
5)輸入平方根為小數的 x
▉ 程式碼實現
寫二分查詢程式碼需要注意的三點:
1)迴圈退出條件。
2)mid 的取值。
3)low 和 hight 的更新。
var mySqrt = function(x) {
let low = 1;
let high = x;
// 如果 x 小於 0 輸出 -1
if(x < 0) return -1;
// 迴圈終止條件
while(low <= high){
// mid 取值
let mid = Math.floor(low + ((high - low)/2));
// 判斷平方是否小於等於
if(Math.pow(mid,2) <= x){
// 如果小於等於,如果下一值大於 x 則當前值為 x 平方根的最小整數值
if(Math.pow(mid+1,2) > x || mid === high){
return mid;
}else{
low = mid + 1;
}
}else{
high = mid - 1;
}
}
return 0;
};
複製程式碼
▉ 效能分析
暴力破解:
- 時間複雜度:O(n)。你需要從 1 遍歷所有可能的資料,所以時間複雜度為O(n)。
- 空間複雜度:O(1)。不需要額外的記憶體空間。
二分法:
- 時間複雜度:O(n)。每次都折半查詢,所以查詢一個元素時間複雜度為O(logn)。
- 空間複雜度:O(1)。不需要額外的記憶體空間。
▉ 小結
通過這個題我們可以總結一下:
1)如果問題涉及到查詢,我們要想到使用二分查詢來提高效率。
2)使用二分查詢之前,判斷問題是否滿足二分查詢的要求。
歡迎一起加入到 LeetCode 開源 Github 倉庫,可以向 me 提交您其他語言的程式碼。在倉庫上堅持和小夥伴們一起打卡,共同完善我們的開源小倉庫! Github:https://github.com/luxiangqiang/JS-LeetCode
歡迎關注我個人公眾號:「一個不甘平凡的碼農」,記錄了自己一路自學程式設計的故事。