在大数组中查找 · Search in a Big Sorted Array(二分法)

本文介绍了一种在未知长度的大数组中使用二分法查找特定元素的方法,该方法首先通过倍增确定搜索范围,然后应用传统二分法实现高效查找。
Description

给一个按照升序排序的正整数数组。这个数组很大以至于你只能通过固定的接口 ArrayReader.get(k) 来访问第k个数。(或者C++里是ArrayReader->get(k)),并且你也没有办法得知这个数组有多大。找到给出的整数target第一次出现的位置。你的算法需要在O(logk)的时间复杂度内完成,k为target第一次出现的位置的下标。

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

Solution

这道题是经典二分法例题的变形,数组为近似无限大,不能直接得到二分的右边界值end,需要先利用倍增的思想确定右边界(动态数组中也用到了这种思想),再利用二分法得到target。

Java

/**
 * 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 can read number by index.
     * @param target: An integer
     * @return : An integer which is the index of the target number
     */
    public int searchBigSortedArray(ArrayReader reader, int target) {
        // Algorithm:
        // 1. get the index that ArrayReader.get(index) >= target in
        //    O(logk)
        // 2. Binary search the target between 0 and index
        
        int index = 1;
        while (reader.get(index - 1) < target) {
            index = index * 2;            //利用倍增的思想确定右边界index
        }
        //进行传统的二分法,找到target
        int start = 0, end = index - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (reader.get(mid) < target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        
        if (reader.get(start) == target) {
            return start;
        }
        
        if (reader.get(end) == target) {
            return end;
        }
        
        return -1;
    }
}

### 查找指定元素的算法 对于在数组中查找指定元素的任务,通常采用线性搜索或二分搜索的方法。当数组未排序时,只能使用线性搜索;而如果数组已经按顺序排列,则可以选择更高效的二分搜索。 #### 线性搜索 这是一种简单直接的方式,在给定的一维数组`list[]`内逐个比较目标值`x`与各元素之间的关系直到发现匹配项为止。这种方法适用于无序列表,并且时间复杂度为O(n),其中n表示数组长度[^1]。 ```c int search_linear(int list[], int n, int x){ for (int i = 0; i < n ; ++i) { if(list[i]==x)return i; } return -1; } ``` #### 有序数组中的插入操作 考虑到特定情况下需要处理的是降序排列的数据结构,为了保持原有秩序不变的情况下完成新成员加入工作,可以从前往后扫描直至遇到首个小于待插数的位置并执行相应移位动作来腾出空间供其安置下去[^2]。 ```c void insert_into_sorted_array_descending_order(int* array,int size,int value){ // 找到第一个比value小的地方 int pos=-1;++i){ if(array[i]<value)pos=i; } // 如果没找到说明应该放在最后面 if(pos==-1)pos=size; // 向后移动数据以便于插入新的数值 for(int j=size;j>pos;--j){ array[j]=array[j-1]; } // 插入新值 array[pos]=value; } ``` #### PTA练习题解答框架 根据提供的裁判测试程序样例可以看出此题目的核心在于定义函数`search()`用于返回查询结果索引号或是报告找不到的情况(-1)[^3]。这里给出完整的解决方案如下: ```c #include <stdio.h> #define MAXN 10 // 定义search函数实现逻辑 int search(int list[], int n, int x); int main(){ int i,index,n,x,a[MAXN]; scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); scanf("%d",&x); index=search(a,n,x); if(index!=-1) printf("index=%d\n",index); else printf("Not found\n"); return 0; } /* 实现search功能 */ int search(int list[], int n, int x){ for(int i=0;i<n;i++){ if(x==list[i]) return i; } return -1; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值