@leetcodex的平方根
簡單的數學問題,這並不是一道考驗思路的題,而是考驗演算法運用的問題,怎麼更快的解決才是王道!請看題幹:
實現 int sqrt(int x) 函式。計算並返回 x 的平方根,其中 x 是非負整數。
由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。
示例 1:
輸入: 4示例 2:輸出: 2
輸入: 8首先我們第乙份**給到筆者投機取巧通過的乙份**,請看:輸出: 2
說明: 8 的平方根是 2.82842…,
由於返回型別是整數,小數部分將被捨去。
哇塞,直接把要實現的函式給用進了程式裡面,再來乙個強制型別轉換,居然搞定了。
其實不用強制轉成int應該也能通過,但是為了尊重一下題幹,筆者覺得還是寫一下為好。
那麼言歸正傳,本題的正宗思想是什麼?要找到乙個確定肯定以及絕對存在的答案,為什麼不直接使用查詢演算法呢?於是筆者來了一套二分查詢,請看**:
這份**看似簡單,其實暗藏玄機。由於使用int型別可能無法存下某些資料,故乾脆直接掏出long long來的簡單。定義頭尾中間,最終結果是ans,將其與x比較,如果小了就左端變成mid加一,如果大了就右端變成mid減一,判斷簡單又好用,人見人愛。
那麼如何解決要取整的問題呢,比如示例2中的情況,其中8的平方根並不是乙個整數。不用慌,其實這個問題已經不小心解決了。由於迴圈是執行到m<=n這個情況不滿足為止,此時說明n經過最後一次減一之後已經小於m了,說明減一之前的n值和m值都不滿足,並且是過大,而m一路遍歷過來發現目前的n值是偏小,所以此時的這個偏小的n值正是取整之後得到的答案,直接輸出即可通過。
但是真正的大佬早就看不上二分法了,牛頓迭代法才是真正最最高端的解法,請看**:
牛頓解法公式一目了然:ans=(ans+x/ans)/2 **寫完甚至有些意猶未盡,然而問題已經解決了。
所以這個方法到底是怎麼回事?牛頓迭代法又稱為牛頓-拉夫遜(拉弗森)方法,是乙個快速尋找平方根的解法,具體可以參考兩位大佬的blog
以及裡面有對其詳細的分析過程,在這裡我挑挑重點談一談:
要計算x² = n的解,令f(x)=x²-n,相當於求f(x)=0的解,畫出座標影象,取x0,若x0不是解,做乙個經過(x0,f(x0))點的切線,與x軸的交點為x1,再判斷x1是否是解,如果x1也不是解,做乙個經過(x1,f(x1))點的切線,與x軸的交點為x2,以此類推,可以得到無限趨近於f(x)=0的解xi。
對xi的判斷有兩種方法,一是直接計算f(xi)的值是否為0,二是判斷前後兩個解xi和xi-1是否無限接近。經過(xi, f(xi))這個點的切線方程為f(x) = f(xi) + f』(xi)(x - xi),其中f』(x)為導數,即2x。令切線方程等於0,得xi+1=xi - f(xi) / f』(xi),繼續化簡得 xi+1=xi - (xi² - n) / (2xi) = xi - xi / 2 + n / (2xi) = xi / 2 + n / 2xi = (xi + n/xi) / 2。
那麼實際應用到本題之中,這個最先取得的x0當然就是x/2+1這個值,從這個值往前進行判斷,這種判斷方法能避免之前二分查詢時的挨個判斷的低效率,但是所耗時間也不會因為這個減少特別多,依據之前的公式推斷即可得到乙個最為借鑑的值,最後乙個數的判斷與二分查詢的判斷原理類似,迴圈判斷條件是ans*ans>x,所以也是能直接得到正確答案。
LeetCode x的平方根
在網上學習了其他人的方法以後,寫了出來,學到了新的方法,在此記錄一下 1,返回整型的時候,可以使用二分法 2 返回double時,可以使用牛頓迭代法,a 求取乙個整數的平方根時,其平方根一定是不大於 n 2 1 所以在 0,n 2 1 這個範圍內求取,如下 int mysqrt int x if m...
LeetCode x的平方根
實現int sqrt int x 函式。計算並返回 x 的平方根,其中 x 是非負整數。由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。示例 1 輸入 4輸出 2示例 2 輸入 8輸出 2說明 8 的平方根是 2.82842.由於返回型別是整數,小數部分將被捨去。解題方法 明白開平方根基...
leetcode x 的平方根
實現int sqrt int x 函式。計算並返回 x 的平方根,其中 x 是非負整數。由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。示例 1 輸入 4 輸出 2 示例 2 輸入 8 輸出 2 說明 8 的平方根是 2.82842 由於返回型別是整數,小數部分將被捨去。這道題大體有幾類...