蓝桥_寻找食物储量

问题描述

你是一个冒险家,在一个危机四伏的森林里,你发现了一个隐藏的食物仓库。这个食物仓库由 n 个房间组成,每个房间都有一定数量的食物。你需要找到第一个房间,其中的食物数量大于或等于一个给定的值 x。

这些房间是按食物数量升序排列的。你知道每个房间的食物数量,但由于时间紧迫,你不能一个个房间地去查找。因此,你决定使用二分搜索来快速找到目标房间。

你的任务是编写一个程序,根据每个房间的食物数量和目标值 x,输出第一个食物数量大于或等于 x 的房间的编号。

输入格式

第一行包含一个整数 n,(1≤n≤1e5)(1≤n≤1e5),表示房间的数量。

第二行包含 n 个整数,表示每个房间的食物数量。这些整数是非降序排列的。

第三行包含一个整数 x,(1≤x≤1e9)(1≤x≤1e9),表示目标食物数量。

输出格式

输出一个整数,表示第一个食物数量大于或等于 x 的房间的编号。如果所有房间的食物数量都小于 x,则输出 −1。

样例输入

5
2 5 8 10 15
9

样例输出

4

样例说明

在上述例子中,房间 4 的食物数量为 10,这是第一个大于或等于 9 的值。

测评数据规模

对于 100% 的数据,1≤n≤1e6,并且每个房间的食物数量不超过 1e9。

运行限制

语言最大运行时间最大运行内存
C++3s512M
C3s512M
Java4s512M
Python35s512M
PyPy35s512M
Go5s512M
JavaScript5s

512M

 解题思路

题中的 '升序排序'、'二分搜索'等字眼可以让我们想到用二分查找的方法进行求解。

二分查找有   找前任:返回 >= 目标值 的最靠左索引

                     找后任:返回 <= 目标值 的最靠右索引

                     找目标值:返回 = 目标值的索引

这几种大致的类型(不全)。

这一题用找前任/后任都可以通过,不过我觉得使用找后任的方法虽然能通过所有的数据,但是万一有若干个相同的x出现,那么找到的索引就是最右侧的x索引,此时就与题中要求(找到第一个>=x的房子编号)相矛盾,所以这个地方我比较推荐使用找前任的方法。

代码

import java.util.Scanner;
public class 寻找食物储量 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < a.length; i++) {
            a[i] = sc.nextInt();
        }
        int x = sc.nextInt();
        int ans = leftmost(a, x);
        System.out.println(ans);
    }
    public static int leftmost(int[] a, int target) {
        int i = 0, j = a.length - 1;
        while (i <= j) {
            int m = (i + j) >>> 1;
            
            //如果目标值target大于当前的数据,那么左边界往右缩
            if(a[m] < target) {
                i = m + 1;
            }

            //如果目标值target小于等于当前数据,右边界不断往左缩(为了找到最左侧符合条件的数据)
            else {
                j = m - 1;
            }
        }
        
        //由于左侧边界i代表的是索引,若是左边第几个,i还应该 + 1
        return (i < a.length)?i + 1:-1;
    }
}

ps:学了b站,现学现卖🤭,有不准确的地方还请大家多多指正(●'◡'●)。

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值