P2249 查找 题解
P2249 查找
题面理解:
首先看下题,非常易懂,就是给你一个单调不减的序列,给你
思路分析:
我这个juruo首先想到的是枚举,但是————(战术性延长)注意:多测!直接枚举时间复杂度就直接**
首先提供个用while循环实现的代码:
#include<bits/stdc++.h>
using namespace std;
int n, m, a[1000005];
int find(int l, int r, int x) {
while (l < r) {
int mid = l + (r - l) / 2; // 取中值
if (x < a[mid]) // 在左区间 (小于中值), 右端点合并mid
r = mid - 1;
if (x > a[mid]) // 在右区间 (大于中值), 左端点合并mid
l = mid + 1;
if (x == a[mid]) // 在看下在仍 l < r (有别的数)的情况下, 右端点合并mid找左边有没有下标更小的
r = mid;
}
if (a[r] == x)
return r;
else return -1;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) { // m次询问
int win;
scanf("%d", &win);
int ans = find(1, n, win); // 调用函数
printf("%d ", ans);
}
return 0;
}
再提供一个递归法:
#include<bits/stdc++.h>
using namespace std;
int n, m, a[1000005];
int find(int l, int r, int x) {
int mid = l + (r - l) / 2;// 取中值
if (l < r) {
if (x > a[mid])
return find(mid + 1, r, x); // 在左区间 (小于中值), 右端点合并mid
if (x < a[mid])
return find(l, mid - 1, x); // 在右区间 (大于中值), 左端点合并mid
if (x == a[mid]) // 在看下在仍 l < r (有别的数)的情况下, 右端点合并mid找左边有没有下标更小的
return find(l, mid, x);
}
if (a[mid] == x) // 注意这里要用mid, 因为人家r是不会变化滴!
return mid;
else return -1;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) {
int win;
scanf("%d", &win);
int ans = find(1, n, win); // 调用
printf("%d ", ans);
}
return 0;
}
ok, 完结撒花(不可能) 可是由于二叉的代码又臭又长,一旦写错了一点儿,怎么办?(A:凉拌) 凉拌 ,给了我们几个锦袋! 下面我来列举一下:
binary_search(beg,end,val)返回一个bool变量,以二分法检索的方式在[beg,end]之间查找val ,找到返回true ,找不到返回false 。lower_bound(beg,end,val)返回一个迭代器,指向非递减序列[first, last)中的第一个大于等于(>=)val 的位置。upper_bound(beg,end,val)返回一个迭代器,指向非递减序列[first, last)中的第一个大于 (>)val 的位置。