binary search總結(1)

模版:左閉右開[lo, hi)
僞碼以下:算法

def binarySearch(lo, hi) {
    while (lo < hi) {
        int mid = (hi-lo)/2+lo;
        if (f(m))    return m // 這一步是optional的
        if (g(m))    hi = mid; // 更新爲[lo, mid)
        else    lo = mid+1;    // 更新爲[mid-1, hi)
    }
    return lo or not found    // 返回的lo是知足g(m)的最小index
}

因此當咱們要在一個有序的區間內尋找到第一個知足條件的數的時候,能夠用binary search來查找。
如162題Find Peak Element這一題,須要咱們找到一個局部峯值,題目要求的時間複雜度是logN,因此就想到能夠用binary search來作,可是binary search怎麼寫一開始是沒有思路的,比較nums[mid]和nums[mid-1],mums[mid+1]的大小嗎?若是mums[mid] > mums[mid-1]該怎麼搜索呢?數組

可是這一題咱們會用O(N)的算法把數組掃描一遍獲得峯值(這種方法我也沒想出來,我一直在考慮和兩邊的值比較,但其實只要比較一邊的大小就能夠了)。也就是咱們找到第一個符合nums[i] > nums[i+1]的i,就是咱們要找的第一個峯值的index。代碼以下:code

class Solution {
    public int findPeakElement(int[] nums) {
        for(int i = 0; i < nums.length-1; i ++) {
            if (nums[i] > nums[i+1])
                return i;
        }
        return nums.length-1;
    }
}

看到這裏就能當即聯想到能夠用binary search改寫這段代碼,代碼以下:get

class Solution {
    public int findPeakElement(int[] nums) {
        int lo = 0, hi = nums.length-1;
        while (lo < hi) {
            int mid = (hi-lo)/2+lo;
            if (nums[mid] > nums[mid+1])
                hi = mid;
            else    lo = mid+1;
        }
        return lo;
    }
}

再看一道很是基礎的題目3五、Find Insert Position,在一個sorted array中尋找某個數,若是這個數存在就返回它的index,若是不存在則返回它應該插入的位置。本質是一道求lower_bound的問題,也就是找到第一個使得nums[i] >= target的i,代碼以下:it

class Solution {
    public int searchInsert(int[] nums, int target) {
        int lo = 0, hi = nums.length;
        while (lo < hi) {
            int mid = (hi-lo)/2+lo;
            if (nums[mid] >= target)    hi = mid;
            else    lo = mid+1;
        }
        return lo;
    }
}

34題Find First and Last Position。在一個存在重複元素的sorted array裏,給定一個target,找到target第一次出現的位置和最後一次出現的位置,若是不存在則返回-1。第一次出現的位置:求lowerbound,最後一次出現的位置:upperbound-1。代碼以下:io

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res = new int[2];
        Arrays.fill(res, -1);
        if (nums == null || nums.length == 0)   return res;
        int lo = 0, hi = nums.length;
        while (lo < hi) {
            int mid = (hi-lo)/2+lo;
            if (target <= nums[mid])    hi = mid;
            else    lo = mid+1;
        }
        if (lo == nums.length || nums[lo] != target) return res;
        res[0] = lo;
        hi = nums.length;
        while (lo < hi) {
            int mid = (hi-lo)/2+lo;
            if (target < nums[mid]) hi = mid;
            else    lo = mid+1;
        }
        res[1] = lo-1;
        return res;
    }
}
相關文章
相關標籤/搜索