【刷題】Search in a Big Sorted Array

原題戳我java

題目

Description

Given a big sorted array with positive integers sorted by ascending order. The array is so big so that you can not get the length of the whole array directly, and you can only access the kth number by ArrayReader.get(k) (or ArrayReader->get(k) for C++). Find the first index of a target number. Your algorithm should be in O(log k), where k is the first index of the target number.git

Return -1, if the number doesn't exist in the array.github

Notice:
If you accessed an inaccessible index (outside of the array), ArrayReader.get will return 2147483647.數組

Example

  • Given [1, 3, 6, 9, 21, ...], and target = 3, return 1.
  • Given [1, 3, 6, 9, 21, ...], and target = 4, return -1.

Challenge

O(log k), k is the first index of the given target number.less

Tags

Sorted Array Binary Searchide

分析

這道題我是看題解才作出來的,思路很是好,有兩個重點:優化

  1. 能夠O(logk)的時間縮小二分法的範圍
  2. 從而,能夠將二分的最壞時間優化到O(logk)

第二點無需證實,下面講解第一點。code

以O(logk)的時間縮小二分法的範圍

若是從0遍歷到k,那麼明顯時間複雜度爲O(k),超過了了O(logk)。ip

要記得,咱們的目的是肯定一個數組的上界r,使O(r)=O(k),繼而在這段數組上進行二分查找,複雜度爲O(logk)。所以,咱們只須要將在O(logk)的時間內找到該r。get

r的要求以下:

  1. 知足O(r)=O(k)
  2. 計算r的時間爲O(logk)

即,尋找一個運算,進行O(logk)次,結果爲O(k)。因而想到了乘冪

2 ** O(logk) = O(k)

代碼以下:

private int[] computeRange(ArrayReader reader, int target){
        int r = 1;
        while (reader.get(r) < target) {
            r <<= 1;
        }
        
        int l = r >> 1;
        while (r >= l && reader.get(r) == 2147483647) {
            r--;
        }
        if (r < l) {
            return null;
        }
        
        return new int[]{l, r};
    }

完整代碼

/**
 * Definition of ArrayReader:
 * 
 * class ArrayReader {
 *      // get the number at index, return -1 if index is less than zero.
 *      public int get(int index);
 * }
 */
public class Solution {
    /**
     * @param reader: An instance of ArrayReader.
     * @param target: An integer
     * @return : An integer which is the index of the target number
     */
    public int searchBigSortedArray(ArrayReader reader, int target) {
        // write your code here
        if (reader == null) {
            return -1;
        }
        
        if (reader.get(0) > target) {
            return -1;
        }
        
        int[] range = computeRange(reader, target);
        if (range == null) {
            return -1;
        }
        
        int k = bsearchLowerBound(reader, range[0], range[1], target);
        if (reader.get(k) != target) {
            return -1;
        }
        
        return k;
    }
    
    private int[] computeRange(ArrayReader reader, int target){
        int r = 1;
        while (reader.get(r) < target) {
            r <<= 1;
        }
        
        int l = r >> 1;
        while (r >= l && reader.get(r) == 2147483647) {
            r--;
        }
        if (r < l) {
            return null;
        }
        
        return new int[]{l, r};
    }
    
    private int bsearchLowerBound(ArrayReader reader, int l, int r, int v) {
        while (l < r) {
            int m = l + (r - l) / 2;
            if (reader.get(m) >= v) {
                r = m;
            } else {
                l = m + 1;
            }
        }
        return l;
    }
}

本文連接:【刷題】Search in a Big Sorted Array
做者:猴子007
出處:https://monkeysayhi.github.io
本文基於 知識共享署名-相同方式共享 4.0 國際許可協議發佈,歡迎轉載,演繹或用於商業目的,可是必須保留本文的署名及連接。

相關文章
相關標籤/搜索