迷宫的寻宝游戏
题目理解
这道题目描述了一个"整数迷宫"的寻宝场景,我们需要解决的核心问题是:给定一组数字集合,然后快速判断多个查询数字是否存在于这个集合中。
输入要求:
-
第一行两个整数N和M,分别表示数字集合的大小和查询次数
-
第二行包含N个整数的集合
-
接下来M行,每行一个查询数字d
输出要求:
-
对于每个查询数字d,如果存在于集合中输出"Yes",否则输出"No"
解题思路
-
数据规模分析:题目给出的N可以达到10^6,M可以达到10^4,这意味着我们需要一个高效的查找算法。
-
算法选择:
-
直接遍历查找:时间复杂度O(M*N),对于最大数据量会是10^10次操作,显然太慢
-
二分查找:先排序(O(N log N)),然后每次查询O(log N),总复杂度O(N log N + M log N),完全能够处理题目给出的数据规模
-
-
实现步骤:
-
读取输入数据
-
对数字集合进行排序(为二分查找做准备)
-
对于每个查询数字,使用二分查找判断是否存在
-
输出结果
-
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5; // 定义数组最大大小,比题目要求的1e6稍大一些
int a[N], n, m; // a数组存储数字集合,n是集合大小,m是查询次数
int main() {
// 读取输入
cin >> n >> m; // 读取数字集合大小n和查询次数m
for (int i = 1; i <= n; i++) cin >> a[i]; // 读取n个数字到数组中
// 对数组进行排序,为二分查找做准备
// 注意这里排序范围是从a[1]到a[n],因为题目中数组是从1开始使用的
sort(a+1, a+1+n);
// 处理每个查询
for (int i = 1; i <= m; i++) {
int L = 1, R = n, target; // 初始化二分查找的左右边界
bool f = false; // 标记是否找到目标
cin >> target; // 读取当前要查询的数字
// 二分查找过程
while (L <= R) {
int mid = (L + R) / 2; // 计算中间位置
if (a[mid] == target) { // 如果找到目标
f = true; // 设置标记为true
break; // 退出循环
} else if (a[mid] < target) { // 如果中间值小于目标
L = mid + 1; // 调整左边界
} else { // 如果中间值大于目标
R = mid - 1; // 调整右边界
}
}
// 输出结果
if (f) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
复杂度分析
-
时间复杂度:
-
排序操作:O(N log N)
-
M次二分查找:O(M log N)
-
总时间复杂度:O((N + M) log N)
-
-
空间复杂度:
-
O(N),用于存储数字集合
-
优化思考
如果数据范围进一步增加,可以在输入时使用scanf的方式提高输入效率:

浙公网安备 33010602011771号