難度:簡單java
題庫地址:leetcode-cn.com/problems/sq…算法
實現 int sqrt(int x)
函數。數組
計算並返回 x 的平方根,其中 x 是非負整數。bash
因爲返回類型是整數,結果只保留整數的部分,小數部分將被捨去。函數
示例 1:spa
輸入: 4
輸出: 2
複製代碼
示例 2:code
輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842..., 因爲返回類型是整數,小數部分將被捨去。
複製代碼
計算x
的平方根,這裏暫不考慮各類求平方根的計算公式。cdn
最簡單的方法就是i
從0開始以步長1遞增,當遇到第一個數i
,使得i * i > x
,那麼i - 1
就是要找的數。固然這裏有個問題,i * i
可能致使計算結果溢出變成死循環。正確的退出條件是當i > x / i
,這樣變化後須要注意i
不能爲0。對象
Java實現:blog
public int mySqrt(int x) {
if (x < 2) {
return 0;
}
int i = 1;
while (i <= x / i) {
i++;
}
return i - 1;
}
複製代碼
以上算法能夠理解爲在[1, x]
中找數i
,由於這裏的[1, x]
已經按升序排好順序,因此可使用二分查找法減小查找次數。 這裏比較麻煩的地方是如何調整查找區間和找到循環終止條件。和在排好序的數組中查找一個數的位置不一樣的是:這裏要查找數x的平方根整數部分。剛開始把問題想的很複雜,好比:
實時證實這些考慮只是在給本身挖坑,在Mr__Kim的評論裏說明了一種簡單明瞭的解決辦法,對於這個算法有以下優勢:
x = 0
的狀況Java代碼以下:
public int mySqrt(int x) {
int l = 1;
int r = x;
// 默認結果爲0,若是x = 0,不會進入循環,直接退出
int ans = 0;
while (l <= r) {
int mid = l + (r - l) / 2;
// 要找的結果是真正平方根的向下取整值,
// 因此 mid <= x / mid 時,隨着查找分區的調整,這個 mid 就無限逼近於最後要找的值
// 最後當退出循環時,這個 ans 就保存了最接近於真正的平方根的值,如 4 -> 2,8 -> 2
if (mid <= x / mid) {
// 實時保存最接近於平方根的結果
ans = mid;
// 因爲當 mid == x / mid 時,已經將當前 mid 值保留了下來,因此下一次調整分區沒必要包含 mid
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
複製代碼
運行結果: