二分法+时间复杂度

题目描述

蒜头君手上有个长度为 n 的数组 A。由于数组实在太大了,所以蒜头君也不知道数组里面有什么数字,所以蒜头君会经常询问整数 x 是否在数组 A 中。

输入格式

第一行输入两个整数 n 和 m,分别表示数组的长度和查询的次数。

接下来一行有 n 个整数 ai​。

接下来 m 行,每行有 1 个整数 x,表示蒜头君询问的整数。

输出格式

对于每次查询,如果可以找到,输出"YES",否则输出"NO"

数据范围

1≤n,m≤105,0≤x≤106。

输入样例 

10 5
1 1 1 2 3 5 5 7 8 9
0
1
4
9
10

输出样例

NO
YES
NO
YES
NO

快速排序原理:
取初始基准值,将数组中其它元素与基准值比较,根据大小分别放置在基准值的左右。
一轮比较后,确定该基准值在数组中的确切位置。再将该位置前后所有元素分成两个数组,重复上述过程,直到最后只剩下一个数进入下一轮,则重复完毕
。 

二分法原理

基本思想:假设数据是按升序排序的,对于给定值n,从序列的中间位置mid开始比较,
如果当前位置arr[mid]值等于n,则查找成功;
若n小于当前位置值arr[mid],则在数列的前半段中查找,arr[left,mid-1];
若n大于当前位置值arr[mid],则在数列的后半段中继续查找arr[left+1,right]。

解题思路 

将这n个数放入数组,让后调用快速排序的函数将数组排序,之后调用二分函数依次输入m个数和排序好的数组一并输入二分函数中,在二分函数中查找数组中是否有该数,输出YES或NO。

运行代码

#include <stdio.h>
void quickSort(int arry[], int low, int high);   //快速排序函数
int search(int s[], int n, int x);     //二分法查找函数

int main() {
	int n, m, t, c;
	scanf("%d %d", &n, &m);
	int a[n], i;
	for (i = 0; i < n; i++) { //将这n个数放入数组
		scanf("%d", &a[i]);
	}
	i = 0;
	t = n - 1;
	quickSort(a, i, t);    //调用快速排序函数,将数组排序
	int k = 0;
	for (i = 0; i < m; i++) {  
		scanf("%d", &c);    //循环输入m个数
		k = search(a, n, c);   //调用二分函数,查找输入的数是否存在于数组中
		if (k == 1) {
			printf("YES\n");
		} else {
			printf("NO\n");
		}
	}
	return 0;
}

//快速排序
void quickSort(int arry[], int low, int high) {
	if (low > high) {
		return;
	}
	int i = low, j = high, temp = arry[i];//获取左右和基准数
	while (i < j) {
		while (temp < arry[j] && i < j) {
			j--;
		}
		if (i < j) {
			arry[i++] = arry[j];
		}
		while (temp > arry[i] && i < j) {

			i++;
		}
		if (i < j) {
			arry[j--] = arry[i];
		}
	}
	arry[i] = temp;

	quickSort(arry, low, i - 1);//左边
	quickSort(arry, i + 1, high);//右边
}

int search(int s[], int n, int x) {
	int low = 0, high = n - 1, mid = 0;  //确定数组边界low和high
	while (low <= high) {
		mid = (low + high) / 2;    //取数组中间值
		if (x > s[mid]) {    //如果待查找的数大于s[mid]
			low = mid + 1;   //令数组左边界=mid+1
		} else if (x < s[mid]) { //如果待查找的数小于s[mid]
			high = mid - 1;    //令函数右边界=mid-1
		} else if (s[mid] == x) {   //直到找到s[mid]=待查找的数,返回1
			return 1;
		}
	}
	return 0;   //找不到该数返回0
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值