【两次过】【二分查找】Lintcode 447. 在大数组中查找

本文介绍了一种在大型升序排列的非负整数数组中,使用二分查找法寻找特定目标值首次出现位置的高效算法。由于数组过大且长度未知,通过倍增法确定右边界,实现O(logk)时间复杂度内的查找,其中k为目标值首次出现的下标。文章详细解释了解决方案,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给一个按照升序排序的非负整数数组。这个数组很大以至于你只能通过固定的接口 ArrayReader.get(k) 来访问第k个数(或者C++里是ArrayReader->get(k)),并且你也没有办法得知这个数组有多大。

找到给出的整数target第一次出现的位置。你的算法需要在O(logk)的时间复杂度内完成,k为target第一次出现的位置的下标。

如果找不到target,返回-1。

样例

样例 1:

输入: [1, 3, 6, 9, 21, ...], target = 3
输出: 1

样例 2:

输入: [1, 3, 6, 9, 21, ...], target = 4
输出: -1

挑战

O(logn)的时间复杂度,n是target第一次出现的下标。

注意事项

如果你访问了一个不可访问的下标(比如越界),ArrayReader 会返回2147483647


解题思路:

显然是二分查找,但是此题没有右边界,需要我们先确定右边界后再二分查找。

确定右边界可以采用倍增法,初始右边界为1, 如果右边界的数小于 target, 就将其倍增, 直到右边界不小于target. 这时就可以二分查找了.

注意: 越界访问是没有关系的, 因为这个ArrayReader在越界访问时, 返回 INT_MAX, 一定不小于 target. 而即使是返回 -1 之类的数值, 我们也可以加一个判断搞定.

/**
 * Definition of ArrayReader:
 * 
 * public class ArrayReader {
 * public int get(int index) {
 *          // return the number on given index, 
 *          // return 2147483647 if the index is invalid.
 *     }
 * };
 */
public class Solution {
    /*
     * @param reader: An instance of ArrayReader.
     * @param target: An integer
     * @return: An integer which is the first index of target.
     */
    public int searchBigSortedArray(ArrayReader reader, int target) {
        // write your code here
        int l = 0;
        int r = 1;
        while (reader.get(r) < target)     // 越界返回INT_MAX, 必然大于target, 所以没有关系
            r <<= 1;
        
        while(l < r){
            int mid = (r+l)>>1;
                
            if(reader.get(mid) >= target)
                r = mid;
            else
                l = mid + 1;
        }
        
        if(reader.get(l) != target)
            return -1;
        return l;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值