1. 程式人生 > >C#LeetCode刷題之#278-第一個錯誤的版本(First Bad Version)

C#LeetCode刷題之#278-第一個錯誤的版本(First Bad Version)

問題

你是產品經理,目前正在帶領一個團隊開發新的產品。不幸的是,你的產品的最新版本沒有通過質量檢測。由於每個版本都是基於之前的版本開發的,所以錯誤的版本之後的所有版本都是錯的。

假設你有 n 個版本 [1, 2, ..., n],你想找出導致之後所有版本出錯的第一個錯誤的版本。

你可以通過呼叫 bool isBadVersion(version) 介面來判斷版本號 version 是否在單元測試中出錯。實現一個函式來查詢第一個錯誤的版本。你應該儘量減少對呼叫 API 的次數。

給定 n = 5,並且 version = 4 是第一個錯誤的版本。

呼叫 isBadVersion(3) -> false
呼叫 isBadVersion(5) -> true
呼叫 isBadVersion(4) -> true

所以,4 是第一個錯誤的版本。 


You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.

Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the following ones to be bad.

You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.

Given n = 5, and version = 4 is the first bad version.

call isBadVersion(3) -> false
call isBadVersion(5) -> true
call isBadVersion(4) -> true

Then 4 is the first bad version. 


示例

public class Program {

    public static void Main(string[] args) {
        var n = 5;
        var res = FirstBadVersion(n);
        Console.WriteLine(res);

        n = 5;
        res = FirstBadVersion2(n);
        Console.WriteLine(res);

        Console.ReadKey();
    }

    private static bool IsBadVersion(int version) {
        return version >= 4;
    }

    private static int FirstBadVersion(int n) {
        //LeetCode超時未AC
        //暴力求解
        for (var i = 0; i < n; i++) {
            if (IsBadVersion(i + 1)) return i + 1;
        }
        return -1;
    }

    private static int FirstBadVersion2(int n) {
        //二分求解
        var low = 1;
        var high = n;
        while (low < high) {
            //取中間索引,並不是每次取半,而是使用 (high - low) / 2 防止過界
            var mid = low + (high - low) / 2;
            //如果是錯誤的版本,直接將右指標指向 mid
            //因為要找的點肯定在它左側
            if (IsBadVersion(mid)) high = mid;
            //如果不是錯誤的版本,將左指標指向 mid + 1
            //因為要找的點肯定在它右側
            else low = mid + 1;
        }
        return low;
    }

}

以上給出2種演算法實現,以下是這個案例的輸出結果:

4
4

分析:

顯而易見,FirstBadVersion  的時間複雜度為:O(n)  ,FirstBadVersion2 的時間複雜度為: O(logn) 。