二分练习题2 查找大于等于x的最小元素 题解
题目描述
现在告诉你一个长度为 \(n\) 的有序数组 \(a_1, a_2, ..., a_n\) ,以及 \(q\) 次询问,每次询问会给你一个数 \(x\) ,对于每次询问,你需要输出数组 \(a\) 中大于等于 \(x\) 的最小元素。
输入格式
输入的第一行包含一个整数 \(n(1 \le n \le 100000)\) ,用于表示数组中元素的个数。
输入的第二行包含 \(n\) 个整数,两两之间有一个空格,用于表示数组中的元素 \(a_1, a_2, ..., a_n(1 \le a_i \le 10^9,并且 a_1 \le a_2 \le ... \le a_n)\) 。
输入的第三行包含一个整数 \(q(1 \le q \le 100000)\) ,用于表示询问的次数。
接下来 \(q\) 行,每行包含一个整数 \(x(1 \le x \le 10^9)\) ,表示要询问的数。
输出格式
对于每一次询问的 \(x\) ,如果数组 \(a\) 中存在大于等于 \(x\) 的元素,则输出数组 \(a\) 中满足大于等于 \(x\) 条件的所有元素中最小的元素;否则输出“-1” 。每个输出结果占单独的一行。
样例输入
5
1 3 5 7 9
3
2
9
11
样例输出
3
9
-1
题目分析
本题涉及算法:二分。
因为数组是按照单调非递增的顺序给我们的(即满足 \(a_i \le a_{i+1}\) ),所以我们按照如下方式进行二分:
首先我们开一个变量 \(L = 1\) 用于表示初始时自变量(数组坐标)的左边界;在一个变量 \(L = n\) 用于表示初始时自变量(数组坐标)的右边界。
我们还需要开一个变量 \(res\) 用于存储答案(即大于等于 \(x\) 的最大的数),初始时 \(res = -1\) (如果结束的时候 \(res\) 还是 \(-1\) 则说明没有符合要求的答案)。
然后只要满足 \(L \le R\) 条件,我们就循环执行如下操作:
开一个变量 \(mid\) 并令 \(mid = (L+R)/2\) ,然后判断:
- 如果 \(a[mid] \ge x\) ,说明这个 \(a[mid]\) 是满足 \(\ge x\) 的当前最优解;所以我们需要将 \(res\) 更新为 \(mid\) ,同时执行 \(R = mid-1\) 。因为当前最优解并不一定是最终最优解,\(a[mid] \ge x\) 能够说明的是 \([mid,R]\) 范围内的所有元素都 \(\ge x\) ,但是并不能说明 \([L, mid-1]\) 范围内是否还存在比 \(a[mid]\) 更小的元素同样 \(\ge x\) ,所以我们还是要继续循环的进左半边去查找(所以才需要执行 \(R = mid -1\) 操作)。
- 如果 \(a[mid] \lt x\) ,说明 \(a[L]\) 到 \(a[mid]\) 范围内的所有元素都 \(\lt x\) ,所以我们只需要执行 \(L = mid +1\) 进右半边继续查找。
这样,当循环结束的时候(不满足 \(L \le R\) 条件则循环就结束了):
- 如果 \(R = -1\) ,说明没有找到答案(因为只要找到答案 \(res\) 就会更新,如果到循环结束的时候 \(res\) 还是等于 \(-1\) 则说明一个满足要求的答案都没有找到过);
- 否则,\(res\) 对应的就是大于等于 \(x\) 的最小元素的坐标,我们直接输出 \(a[res]\) 即可。
这里需要注意的是:一旦找到了当前最优解,我就更新 \(res\) 为 \(mid\) (令 \(res\) 记录最优解的自变量);但是其实我们也可以更新 \(res\) 为 \(a[mid]\)(令 \(res\) 记录最优解的应变量)。之所以我更习惯用 \(res\) 记录自变量的原因是:可以直接通过自变量得到应变量,而不能直接通过应变量得到自变量,所以使用 \(res\) 记录自变量会好一些。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, a[maxn], q, x;
// solve函数用于返回大于等于x的最小元素
int solve(int x) {
int L = 1, R = n, res = -1;
while (L <= R) {
int mid = (L + R) / 2;
if (a[mid] >= x) {
res = mid;
R = mid - 1;
}
else L = mid + 1;
}
if (res == -1) return -1; // 如果循环结束res==-1,说明没有找到答案
return a[res]; // 因为res存的是最优解的坐标,所以返回a[res]
}
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
cin >> q;
while (q --) {
cin >> x;
cout << solve(x) << endl;
}
return 0;
}
二分练习题2 查找大于等于x的最小元素 题解的更多相关文章
- 二分练习题3 查找小于x的最大元素 题解
题目描述 现在告诉你一个长度为 \(n\) 的有序数组 \(a_1, a_2, ..., a_n\) ,以及 \(q\) 次询问,每次询问会给你一个数 \(x\) ,对于每次询问,你需要输出数组 \( ...
- P1042 查找大于等于x的最小元素
题目描述 现在告诉你一个长度为 \(n\) 的有序数组 \(a_1, a_2, ..., a_n\) ,以及 \(q\) 次询问,每次询问会给你一个数 \(x\) ,对于每次询问,你需要输出数组 \( ...
- 笔试算法题(05):转换BST为双向链表 & 查找栈中的最小元素
出题:把二元查找树转变成排序的双向链表.输入一棵二元查找树,要求将该二元查找树按照中序转换成一个排序的双向链表,要求不能创建任何新的节点,只能调整指针的指向: 分析: 递归的思路,当前节点需要进行的处 ...
- python 练习题:使用迭代查找一个list中最小和最大值,并返回一个tuple
# -*- coding: utf-8 -*- # 请使用迭代查找一个list中最小和最大值,并返回一个tuple from collections import Iterable def findM ...
- 【Python实践-5】使用迭代查找一个list中最小和最大值
# -*- coding: utf-8 -*- #使用迭代查找一个list中最小和最大值,并返回一个tuple #遍历list,找到最小值 def findMinAndMax(L): if L==[] ...
- 9.算法之顺序、二分、hash查找
一.查找/搜索 - 我们现在把注意力转向计算中经常出现的一些问题,即搜索或查找的问题.搜索是在元素集合中查找特定元素的算法过程.搜索通常对于元素是否存在返回 True 或 False.有时它可能返回元 ...
- 请使用迭代查找一个list中最小和最大值,并返回一个tuple
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 在Python中,迭代是通过for ... in来完成的,而很多语 ...
- 计蒜客 41387.XKC's basketball team-线段树(区间查找大于等于x的最靠右的位置) (The Preliminary Contest for ICPC Asia Xuzhou 2019 E.) 2019年徐州网络赛
XKC's basketball team XKC , the captain of the basketball team , is directing a train of nn team mem ...
- 算法之顺序、二分、hash查找
算法之顺序.二分.hash查找 一.查找/搜索 - 我们现在把注意力转向计算中经常出现的一些问题,即搜索或查找的问题.搜索是在元素集合中查找特定元素的算法过程.搜索通常对于元素是否存在返回 Tru ...
随机推荐
- Windows Server 2008利用NTFS管理数据
今天我们学习关于NTFS管理数据 以下是学习的内容NTFS分区和FAT32分区的区别,如何将FAT32分区转化成NTFS分区,FAT 32 不支持大于4G ,NTFS权限设置 ,EFS加密 ,文件夹的 ...
- 【I'm Telling the Truth】【HDU - 3729】 【匈牙利算法,DFS】
思路 题意:该题主要说几个同学分别说出自己的名次所处区间,最后输出可能存在的未说谎的人数及对应的学生编号,而且要求字典序最大. 思路:刚刚接触匈牙利算法,了解的还不太清楚,附一个专门讲解匈牙利算法的博 ...
- 解决Springboot整合ActiveMQ发送和接收topic消息的问题
环境搭建 1.创建maven项目(jar) 2.pom.xml添加依赖 <parent> <groupId>org.springframework.boot</group ...
- 一份程序猿单词列表(updating)
以下单词是个人平时阅读英文文档时遇到的一些“生”单词,该文档将持续更新,可以持续关注https://github.com/hylinux1024/word-list-for-programmer hi ...
- tracert和traceroute介绍
一.tracert和traceroute简介 相同点:都是用来跟踪路由,帮助排查问题,关注的是过程,而ping关注的是结果 不同点:tracert请求是icmp echo报文 traceroute请求 ...
- Socket通信封装MIna框架--含羞代放
目录 核心类 各个击破 IoService IoFilter IoHandler 总结 # 加入战队 微信公众号 Mina异步IO使用的Java底层JNI框架,Mina提供服务端和客户端,将我们的业务 ...
- hive动态分区与静态分区
测试目的:1.分区表的动态分区与静态分区2.每层数据,数据流向,数据是否在每层都保留一份测试结果:1.动态分区/静态分区略2.每层表的数据都会保留,因此在生产上odm层的数据是可以删除的(不管是内表还 ...
- Entity Framework 6.0 入门系列 第一篇
Entity Framework 6.0 入门系列 第一篇 好几年前接触过一些ef感觉不是很好用,废弃.但是 Entity Framework 6.0是经过几个版本优化过的产物,性能和功能不断完善,开 ...
- go 学习笔记之详细说一说封装是怎么回事
关注公众号[雪之梦技术驿站]查看上篇文章 猜猜看go是不是面向对象语言?能不能面向对象编程? 虽然在上篇文章中,我们通过尝试性学习探索了 Go 语言中关于面向对象的相关概念,更确切的说是关于封装的基本 ...
- Python程序包的构建和发布过程
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...