YTU 2413 C 语言习题 折半查找 如何应对降序二分

本文介绍了如何在已排序的降序C语言数组中使用折半查找方法找到特定数值首次出现的位置,通过调整搜索边界来确保找到的是第一个小于等于查询值的元素。
摘要由CSDN通过智能技术生成

问题 G: C 语言习题 折半查找

时间限制: 1.00s | 内存限制: 128MB

题目描述

有 n 个数(n≤1000000),这 n 个数已按从大到小顺序存放在一个数组中,然后有 T 次查询,每次输入一个数,要求用折半查找法找出该数在数组中第一次出现的位置。如果不在数组中输出 0

输入

第一行数组元素的个数 nnn。

第二行 nnn 个数组元素的值。

第三行输入查询次数 T(T≤100000)。

往下有 T 行,每行输入一个需要查询的数字。

输出

查找的值在数组中的位置。

输入输出样例

样例输入 #1

复制

10
10 9 8 7 6 5 4 3 2 1
2
9
5
样例输出 #1

复制

2
6

提示

注意:数组空间为 1000000 和 100000。

tips:使用 scanfprintf 会更快哦

我们大家都知道升序的二分如何查找第一个大于等于x 的数字所在的下标,可是你知道如果是降序,你又该如何应呢?
其实二分的关键就是在画图,可以分为两个区间,判断这个数是否满足某个性质,哪个区间段满足这个性质。

升序我们找某个数第一次出现的位置,寻找的是第一次大于这个数,降序寻找的就是第一次小于等于这个数

这道题呢,因为它是降序,我们要找某个数字第一次出现的位置,其实就是找第一个小于等于x 的数字的下标,
比如  

a[i]  10 9 8 7 7 6 5 4 3 2
 i    1  2 3 4 5 6 7 8 9 10

如果mid满足判断条件(a[mid]<=x),并不能说明mid 就是第一个小于等于x的数,mid 右侧的数肯定都满足<=x ,但我们要寻找第一个小于等于x 的数,因此要将r 更新成mid ,即答案在左半边区间,如果不满足条件(即a[mid]>x) ,答案肯定在mid 右侧的区间而且不包含mid ,即l=mid+1;
 

举个例子吧:比如你要找的数字是7, 你mid 是6,a[6]<=7,因为是降序,答案肯定在左边。
它已经小于7了,右边一定小于7 ,你要找第一次小于等于7的,肯定要往左半边(数大的位置)找。

代码实现:
 

#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
int a[N];
int main()
{
    int n;
    cin>>n;
    for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    int T;
    cin>>T;
    while(T--)
    {
        int x;
        scanf("%d",&x);
        int l=1,r=n;
        while(l<r)
        {
            int mid=l+(r-l)/2;
            if(a[mid]<=x) r=mid;
            else l=mid+1;
        }
        if(a[l]!=x) printf("0\n");
        else printf("%d\n",l);
    }
    return 0;
}

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值