山脈數組中查找目標值-二分查找算法

題目

難度困難21
(這是一個 交互式問題 )給你一個 山脈數組 mountainArr,請你返回能夠使得 mountainArr.get(index) 等於 target 最小 的下標 index 值。如果不存在這樣的下標 index,就請返回 -1。

何爲山脈數組?如果數組 A 是一個山脈數組的話,那它滿足如下條件:
首先,A.length >= 3其次,在 0 < i < A.length - 1 條件下,存在 i 使得:A[0] < A[1] < … A[i-1] < A[i]A[i] > A[i+1] > … > A[A.length - 1]
你將 不能直接訪問該山脈數組,必須通過 MountainArray 接口來獲取數據:MountainArray.get(k) - 會返回數組中索引爲k 的元素(下標從 0 開始)MountainArray.length() - 會返回該數組的長度

注意:對 MountainArray.get 發起超過 100 次調用的提交將被視爲錯誤答案。此外,任何試圖規避判題系統的解決方案都將會導致比賽資格被取消。

爲了幫助大家更好地理解交互式問題,我們準備了一個樣例 “答案”:鏈接: https://leetcode-cn.com/playground/RKhe3ave.,請注意這 不是一個正確答案。

示例 1:輸入:array = [1,2,3,4,5,3,1], target = 3
輸出:2
解釋:3 在數組中出現了兩次,下標分別爲 25,我們返回最小的下標 2
示例 2:輸入:array = [0,1,2,4,2,1], target = 3
輸出:-1
解釋:3 在數組中沒有出現,返回 -1

提示:
3 <= mountain_arr.length() <= 100000 <= target <= 10^90 <= mountain_arr.get(index) <= 10^9

通過次數1,811提交次數5,349

思路:

從題目分析我們可知道,此題無法暴力求解,必定超出最大搜索次數。
那麼在衆多查找算法中,我們用哪個呢。此時我們知道,這個數組是左右兩邊有序。因此,我們採用二分查找法,以峯值爲界限,左右分別查找。

代碼:

/**
 * // This is MountainArray's API interface.
 * // You should not implement it, or speculate about its implementation
 * interface MountainArray {
 *     public int get(int index) {}
 *     public int length() {}
 * }
 */
 
class Solution {
    public int findInMountainArray(int target, MountainArray A) {  
    	// 查找峯值
        int peek = findPeek(A);
        //找左區間
        int ansleft = binSearchleft(A,0,peek,target);
        //找右區間
        int ansright = binSearchright(A,peek+1,A.length()-1,target);
        return ansleft>=0?ansleft:ansright;
    }
    
    //左邊升序區間查找
    int binSearchleft(MountainArray A,int l,int rr,int t) {
        int r = rr;
        while(l<r) {
            int mid = (l+r)/2;
            if(A.get(mid)<t)
                l = mid+1;
            else
                r = mid;
        }
        return l<=rr&&A.get(l)==t?l:-1;
    }
    
    //右邊降序區間查找
    int binSearchright(MountainArray A,int l,int rr,int t) {
        int r = rr;
        while(l<r) {
            int mid = (l+r)/2;
            if(A.get(mid)>t)
                l = mid+1;
            else
                r = mid;
        }
        return l<=rr&&A.get(l)==t?l:-1;
    }
    
    //查找峯
    int findPeek(MountainArray A) {
        int l = 0,r = A.length();
        while(l<r) {
            int mid = (l+r)/2;
            if(mid+1<A.length()&&A.get(mid)<A.get(mid+1))
                l = mid+1;
            else
                r = mid;
        }
        return l;
    }
}

小結:

希望看到此篇文章的小夥伴們鞏固複習一下二分查找算法,此算法在算法筆試中出現頻率非常高,博主希望所有小夥伴都能掌握算法的核心思想。不懂的可以私信博主,或者自己動手畫一下,手動執行一下就會明白了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章