顺序查找
- 题目
输入一个数n,然后输入n个不同的数值,再输入一个值x,输出这个值在数组中的下标(从0开始,若不在数组中则输出-1)
输入:
测试数组有多组,输入n(1<=n<=200),接着输入n个数,然后输入x
输出:
对于每组输入,输出结果
样例输入:
2
1 3
9
样例输出
-1
代码
#include <cstdio>
int main() {
int n;
int x;
int arr[200];
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
scanf_s("%d", &x);
int idx;
for ( idx = 0; idx < n; idx++) {
if (arr[idx] == x) {
printf("%d\n", idx);
break;
}
}
if (idx == n) {
printf("-1\n");
}
}
- 顺序查找的问题
有多个不同的x需要查找,效率不高
二分查找
-
注意点
1)有序数组(或者可以转换成有序数组)
2)迭代和边界情况 -
题目
输入数组长度n输入数组,a[1,2,…,n]输入查找个数m,输入查找数字b 输出YES/NO 查找有则输出YES,否则输出NO
输入:
输入有多组数据,每组输入n,然后输入n个整数,再输入m,然后再输入m个整数(1<=m,n<=100)
输出:
如果在n个数组中输出YES否则输出NO
示例
输入:5
1 5 2 4 3
3
2 5 6
输出:
YES
YES
NO
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int arr[100];//全局的数组,方便在不同的函数之间共享
bool binarySearch(int n, int x) {
int left = 0;
int right = n - 1;
while (left<=right) {//最难的点
int mid = (left + right) / 2;
if (arr[mid] == x) {
return true;
}
else if (arr[mid] > x) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
return false;
}
int main() {
int n, m;
while (scanf_s("%d", &n) != EOF) {
for (int i = 0; i < n; i++) {
scanf_s("%d", &arr[i]);
}
//排序
sort(arr , arr + n);
//读取m个数据
scanf_s("%d", &m);
for (int i = 0; i < m; i++) {
int x;
scanf_s("%d", &x);
if (binarySearch(n, x)) {
printf("YES\n");
}
else {
printf("NO\n");
}
}
}
}
- 总结
有序——>若数组本身是无序的——>先排序O(NlogN)
顺序查找 O(N)
二分查找O(logN)
对于无序数组而言,若只查找一次,顺序查找优于二分查找;若查找多次,则二分查找优于顺序查找,前者时间复杂度为O(NlogN+MlogN),后者为O(MN)
二分查找和map的关系
- 用map解决查找问题
键——>数组元素
值——>数组元素的下标
map<int,int>
map容器
代码(上题)
#include <cstdio>
#include<map>
using namespace std;
int main() {
map<int, int>findIndex;
int m, n;
int arr[101];
while (scanf_s("%d", &n) != EOF) {
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
findIndex[arr[i]] = i;
//将数组元的元素作为键,数组元素的下标作为值,插入到map当中
}
scanf_s("%d", &m);
for (int i = 0; i < m; i++) {
int findNum;//待查找元素
scanf_s("%d", &findNum);
if (findIndex.find(findNum) == findIndex.end()) {
printf("NO\n");
}
else {
printf("YES\n");
}
}
}
}
map的底层是一个二叉搜索树
代价:引入更高的空间复杂度