leetcode 69. x 的平方根

69. x 的平方根

難度:簡單java

題庫地址:leetcode-cn.com/problems/sq…算法

1. 題目描述

實現 int sqrt(int x) 函數。數組

計算並返回 x 的平方根,其中 x 是非負整數。bash

因爲返回類型是整數,結果只保留整數的部分,小數部分將被捨去。函數

示例 1:spa

輸入: 4
輸出: 2
複製代碼

示例 2:code

輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842..., 因爲返回類型是整數,小數部分將被捨去。
複製代碼

2. 解題思路

計算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的平方根整數部分。剛開始把問題想的很複雜,好比:

  • 當「中間值」不是要查找的對象時該如何肯定下一個查找範圍
  • 應該在什麼狀況下退出查找
  • 退出查找後,怎麼肯定是在剛恰好的位置(好比 4 -> 2),仍是整數部分(8 -> 2)

實時證實這些考慮只是在給本身挖坑,在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;
}
複製代碼

運行結果:

相關文章
相關標籤/搜索