Java練習(xí)題之實(shí)現(xiàn)平方根(sqrt)函數(shù)
前言
可使用java.lang.Math類(lèi)的sqrt(double)方法求平方根。Math是java.lang包中的類(lèi),而Double為對(duì)象中的基本類(lèi)型。但是如果不使用庫(kù)函數(shù)呢?有什么辦法實(shí)現(xiàn)平方根函數(shù)呢?
方法:二分查找、牛頓迭代法、利用平方數(shù)的性質(zhì)
利用平方數(shù)的性質(zhì)
平方數(shù)的性質(zhì):n²=1+1+2+2+....+n-1+n-1+n。例如4²=1+1+2+2+3+3+4=16。
1+3為2的平方,1+3+5為3的平方,
也就是說(shuō)每一次加一個(gè)奇數(shù),再設(shè)置一個(gè)變量記錄加了多少個(gè)奇數(shù)。
復(fù)雜度分析:
時(shí)間復(fù)雜度:O(N),每次+2的循環(huán),為(1/2)N的時(shí)間復(fù)雜度,去掉系數(shù),為O(N)
空間復(fù)雜度: O(1),只使用了有限常數(shù)個(gè)變量;
int sqrt(int x) { if(x<=0) return 0; //小于等于0 返回0 int ans = 1; int num = 1; int i = 3; while(num+i<=x){ num+=i; ans ++; // 每加一個(gè)奇數(shù),ans+1 i += 2; } return ans; }
二分查找
如果求解一個(gè)數(shù)的平方根,這個(gè)結(jié)果肯定是在1到這個(gè)數(shù)的范圍,因此我們可以使用二分查找的方法。例如求解x的平方根,思路:
- 初始范圍:1 ~ x,使用left標(biāo)記1,right標(biāo)記x ,取left~right的中間值,為 middle;
- 當(dāng)middle*middle <= x && (middle+1)*(middle+1) > x時(shí),返回結(jié)果
- 當(dāng) middle*middle < x時(shí),到右半部分繼續(xù)尋找,范圍改成 middle+1 ~ right
- 當(dāng)middle*middle > x時(shí),到左半部分繼續(xù)尋找,范圍改成 left ~ middle+1
注: 這種方法只能使用于整數(shù)的開(kāi)跟
復(fù)雜度分析:
時(shí)間復(fù)雜度:O(logn),二分查找的復(fù)雜度,每次循環(huán)減少一半
空間復(fù)雜度;O(1),只使用了有限常數(shù)個(gè)變量;
代碼實(shí)現(xiàn):
public int mySqrt(int x) { if (x <= 0) { return 0; } int left = 1, right = x; while (true) { int middle = (left + right) >> 1; if (middle <= x / middle && (middle+1) > x / (middle+1)) { return (int) middle; } else if (middle < x / middle) { left = middle + 1; } else { right = middle - 1; } } }
牛頓迭代法
牛頓迭代法簡(jiǎn)介
假設(shè)方程 F(x)=0 在 x 附近有一個(gè)根,那么用以下迭代式子:
依次計(jì)算X1、X2、X3、...........那么序列將無(wú)限逼近方程的根。
牛頓迭代法的原理很簡(jiǎn)單,其實(shí)是根據(jù)f(x)在x0附近的值和斜率,估計(jì)f(x)和x軸的交點(diǎn),看下面的動(dòng)態(tài)圖:
代碼示例:
public class Solution { public int sqrt (int x) {//牛頓迭代法 if(x==0||x==1) return x;//題中告訴我們x的范圍: 0 <= x < 2^31-1 long X0 = x;//使用int進(jìn)行加法運(yùn)算可能溢出,所以采用long型 long X1 = 0;//下一個(gè)迭代變量,為了方便理解,也可只使用X0 while(X0 > x/X0 ) { // X0^2>x循環(huán) X1=(X0+x/X0) >> 1;//由迭代公式得,采用右移1位操作代替除以2,運(yùn)算更快 X0=X1;//把下一個(gè)迭代變量賦給X0,統(tǒng)一操作,方便繼續(xù)處理 } return (int)X0;//返回值類(lèi)型為int,因此需要做強(qiáng)制類(lèi)型轉(zhuǎn)換 } }
總結(jié)
牛頓迭代法不像二分查找法、平方數(shù),需要喚醒一下各位哥哥姐姐們的高中數(shù)學(xué)知識(shí),只有這樣才能理解該公式。如果喚醒失敗,推薦使用二分查找法,不要逞強(qiáng)哦。
到此這篇關(guān)于Java練習(xí)題之實(shí)現(xiàn)平方根(sqrt)函數(shù)的文章就介紹到這了,更多相關(guān)Java平方根sqrt函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java編程實(shí)現(xiàn)從給定范圍內(nèi)隨機(jī)N個(gè)不重復(fù)數(shù)生成隨機(jī)數(shù)的方法小結(jié)
這篇文章主要介紹了Java編程實(shí)現(xiàn)從給定范圍內(nèi)隨機(jī)N個(gè)不重復(fù)數(shù)生成隨機(jī)數(shù)的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了java根據(jù)指定范圍生成不重復(fù)隨機(jī)數(shù)的相關(guān)操作技巧,需要的朋友可以參考下2017-04-04使用JAVA實(shí)現(xiàn)高并發(fā)無(wú)鎖數(shù)據(jù)庫(kù)操作步驟分享
一個(gè)在線2k的游戲,每秒鐘并發(fā)都嚇?biāo)廊?。傳統(tǒng)的hibernate直接插庫(kù)基本上是不可行的。我就一步步推導(dǎo)出一個(gè)無(wú)鎖的數(shù)據(jù)庫(kù)操作,詳情看下文2013-11-11SpringBatch結(jié)合SpringBoot簡(jiǎn)單使用實(shí)現(xiàn)工資發(fā)放批處理操作方式
這篇文章主要介紹了SpringBatch結(jié)合SpringBoot簡(jiǎn)單使用實(shí)現(xiàn)工資發(fā)放批處理操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09Java?NIO實(shí)現(xiàn)聊天系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java?NIO實(shí)現(xiàn)聊天系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11淺試仿?mapstruct實(shí)現(xiàn)微服務(wù)編排框架詳解
這篇文章主要為大家介紹了淺試仿?mapstruct實(shí)現(xiàn)微服務(wù)編排框架詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08idea指定maven的settings文件不生效的問(wèn)題解決
本文主要介紹了idea指定maven的settings文件不生效的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06如何解決異步線程導(dǎo)致的traceId為空的問(wèn)題
文章討論了在使用異步線程時(shí),traceId為空的問(wèn)題,并提出了使用線程池的解決方案,作者分享了個(gè)人經(jīng)驗(yàn),并鼓勵(lì)大家參考和支持腳本之家2025-02-02Java如何導(dǎo)出多個(gè)excel并打包壓縮成.zip文件
本文介紹了Java如何導(dǎo)出多個(gè)excel文件并將這些文件打包壓縮成zip格式,首先,需要從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)并導(dǎo)出到指定位置形成excel文件,接著,將這些數(shù)據(jù)分散到不同的excel文件中,最后,使用相關(guān)的Java工具類(lèi)對(duì)這些excel文件進(jìn)行打包壓縮2024-09-09