LeetCode算法題-First Bad Version(Java實現(xiàn)-三種解法)

這是悅樂書的第200次更新,第210篇原創(chuàng)

01 看題和準備

今天介紹的是LeetCode算法題中Easy級別的第66題(順位題號是278)。您是產(chǎn)品經(jīng)理,目前領(lǐng)導團隊開發(fā)新產(chǎn)品。不幸的是,您產(chǎn)品的最新版本未通過質(zhì)量檢查。由于每個版本都是基于以前的版本開發(fā)的,因此壞版本之后的所有版本也是壞的。

假設(shè)您有n個版本[1,2,...,n]并且您想找出第一個壞的版本,這會導致以下所有版本都不好。您將獲得一個API bool isBadVersion(版本),它將返回版本是否錯誤。 實現(xiàn)一個函數(shù)來查找第一個壞版本。 您應(yīng)該最小化對API的調(diào)用次數(shù)。

例如:

給定n = 5,版本= 4是第一個壞版本。

調(diào)用isBadVersion(3) - > false

調(diào)用isBadVersion(5) - > true

調(diào)用isBadVersion(4) - > true

然后4是第一個壞版本。

isBadVersion方法在父類VersionControl中定義。

boolean isBadVersion(int version);

本次解題使用的開發(fā)工具是eclipse,jdk使用的版本是1.8,環(huán)境是win7 64位系統(tǒng),使用Java語言編寫和測試。

02 第一種解法

對于從1到n的所有版本中,假設(shè)好壞版本的臨界是第mid個,那么從1到mid-1都是好版本,在調(diào)用isBadVersion方法時總是返回false;從mid到n都是壞版本,調(diào)用isBadVersion方法時返回的都是true。

直接使用for循環(huán),指針從1開始,依次調(diào)用isBadVersion方法,如果返回true,則返回當前指針所表示的版本,反之返回n,即最后一個版本。

此解法的時間復雜度是O(n),空間復雜度是O(1),但是提交后提示超時了,我們需要一個更快的方法。

public int firstBadVersion(int n) {
    for (int i = 1; i < n; i++) {
        if (isBadVersion(i)) {
            return i;
        }
    }
    return n;
}


03 第二種解法

從第一種解法的分析那里,相信你應(yīng)該可以將此問題再抽象下,就變成數(shù)據(jù)查找問題了,從一個指定大小的容器中找出具體的某一個值。

如果你玩過猜大小的游戲,那么使用二分法來求解,你一定不陌生。不斷使用中間數(shù),向預(yù)期的結(jié)果逼近。

使用二分法需要注意兩點:

在求中間數(shù)的時候,如果數(shù)據(jù)類型選用int,直接使用(1+n)/2,如果n是Integer的最大值,加1后會存在溢出的風險,此時我們可以曲線救國,換一種寫法,1 + (n-1)/2,就可以避免這種風險,另外也可以將其換成范圍更大的long類型,不過就需要強轉(zhuǎn)了。

如果中間值調(diào)用isBadVersion方法時返回false,是不能直接判定臨界版本就是mid,因為你無法保證mid的前幾位都是好版本,正確的做法是讓范圍縮小到1到mid,再去求中間值進行判斷。

此解法的時間復雜度是O(log(n)),空間復雜度是O(1)。

public int firstBadVersion2(int n) {
    int left = 1;
    int right = n;
    while (left < right) {
        int mid = (right-left)/2 + left;
        if (isBadVersion(mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return left;
}


04 第三種解法

這是遞歸的解法,思路和第二種解法一樣。

public int firstBadVersion3(int n) {
    if (n == 0) {
        return 0;
    }
    return helper(n, 1, n);
}

public int helper(int n, int start, int end) {
    if (start >= end) {
        return start;
    }
    int middle = start + (end - start)/2;
    if (isBadVersion(middle)) {
        return helper(n, start, middle);
    } else {
        return helper(n, middle + 1, end);
    }
}


05 小結(jié)

算法專題目前已連續(xù)日更超過一個月,算法題文章66+篇,公眾號對話框回復【數(shù)據(jù)結(jié)構(gòu)與算法】、【算法】、【數(shù)據(jù)結(jié)構(gòu)】中的任一關(guān)鍵詞,獲取系列文章合集。

以上就是全部內(nèi)容,如果大家有什么好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉(zhuǎn)發(fā)就是對我最大的回報和支持!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • <center>#1 Two Sum</center> link Description:Given an arr...
    鐺鐺鐺clark閱讀 2,354評論 0 3
  • 今天突然有個極深的感悟,人的改變好難,人從根上的改變好難。上再多的課,讀再多的書,聽再多的演講,拜再多的師父,根上...
    卓萍法皈閱讀 189評論 0 0
  • 創(chuàng)建對象 創(chuàng)建對象方式有很多,每一種都有自己的特點,可以根據(jù)不同場景去選擇創(chuàng)建對象的方式 工廠模式 優(yōu)點:消除了對...
    snailTJ閱讀 350評論 0 0
  • 從朋友圈直接復制粘貼過來了。 大致回憶了一下,今天是跑步的第18天,前12天每天半小時,近6天每天一小時。...
    青草小子是個丫頭閱讀 173評論 0 0
  • 我家三個娃,分別是6歲和4歲哥哥及2歲妹妹,從小作息比較規(guī)律,起床、上學、放學、吃飯、睡覺時間都比較固定。我學習親...
    西貢鮑鮑閱讀 184評論 0 0

友情鏈接更多精彩內(nèi)容