13 在大数组中查找(Search in a Big Sorted Array)

1 题目

题目:在大数组中查找(Search in a Big Sorted Array)
描述:给一个按照升序排序的非负整数数组。这个数组很大以至于你只能通过固定的接口 ArrayReader.get(k) 来访问第k个数(或者C++里是ArrayReader->get(k)),并且你也没有办法得知这个数组有多大。找到给出的整数target第一次出现的位置。你的算法需要在O(logk)的时间复杂度内完成,k为target第一次出现的位置的下标。如果找不到target,返回-1。

  1. 如果你访问了一个不可访问的下标(比如越界),ArrayReader 会返回2,147,483,647。

lintcode:题号——447,难度——medium

样例1:

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

样例2:

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

2 解决方案

2.1 思路

  由于无法知道数组的长度,所以需要自己制定,因为时间复杂度要求时O(log k),二分的时间复杂度是log的数量级,考虑将二分逆向使用,通过倍增的方式来不断寻找符合条件的边界,找到边界之后即可按照标准二分搜索来解题。

倍增思想在很多容器中被使用到,c++中的vector等主要容器起始分配的容量大小都是一定值的(为了不浪费资源),每次在存入的数据即将超出容量的时候,会动态地将容量加倍。

2.2 时间复杂度

  先寻找边界耗时O(log n),再搜索目标耗时O(log n),该题的算法的时间复杂度为O(2*log n) = O(log n)。

深度优先搜索的时间复杂度计算没有通用的方式,只能根据具体题目计算,可以理解成看作答案个数与构造每个答案花费的时间的乘积。

2.3 空间复杂度

  使用了vector数据结构保存节点,算法的空间复杂度为O(n)。

3 源码

细节:

  1. 边界未知,需要先用倍增的方式找到边界。
  2. 有了边界之后就可以使用二分搜索来找到目标。

C++版本:

/**
* @param reader: An instance of ArrayReader.
* @param target: An integer
* @return: An integer which is the first index of target.
*/
int searchBigSortedArray(ArrayReader * reader, int target) {
    // write your code here
    int index = 1;
    // 倍增寻找边界
    while (reader->get(index) < target)
    {
        index *= 2;
    }

    // 找到边界之后,二分搜索目标
    int start = index / 2;
    int end = index;
    while (start + 1 < end)
    {
        int mid = start + (end - start) / 2;
        if (reader->get(mid) < target)
        {
            start = mid;
        }
        if (reader->get(mid) >= target)
        {
            end = mid;
        }
    }

    if (reader->get(start) == target)
    {
        return start;
    }
    if (reader->get(end) == target)
    {
        return end;
    }

    return -1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值