『算法竞赛入门经典(第2版)』5-1 大理石在哪儿?

题目

在这里插入图片描述

1. 思路

用数组(或者vector)收集各个大理石写着的数字元素,先从小到大排序,然后查找指定数字所在位置。
sort(v.begin(),v.end()) :从小到大排序;
lower_bound :查找“大于或等于x的第一个位置”

2. 解决方案

#include<iostream>
#include<algorithm>
using namespace std; 

const int maxn=10000;
int main(){
    
    
	//n:石头个数	q: 问题个数  x:		a[maxn]:石头数组 
	int n,q,x,a[maxn],kase=0;
	
	while(scanf("%d%d",&n,&q)==2&& n){
    
    
		
		printf("case# %d:\n",++kase);
		for(int i=0;i<n;i++){
    
    
			scanf("%d",&a[i]);
		} 			
		sort(a,a+n);	//排序 :a是数组,返回数组首地址 sort(v.begin(),v.end()) 从小到大排序 
		
		while(q--){
    
    
			scanf("%d",&x);//输入寻找的x 
			int p=lower_bound(a,a+n,x)-a;	//找x,大于或等于x的第一个位置 
			if(a[p]==x){
    
    
				printf("%d found at %d\n",x,p+1);
			}else {
    
    
				printf("%d not found\n",x); 
				
			} 
							
		}
	}
	return 0;
}

运行结果:
石头个数:4;问题个数:2;石头数组:5,2,3,1;先给数组排序,结果为:1,2,3,5;问题1:找x=2;问题2:找x=4.
在这里插入图片描述

3. 总结与反思

  1. while(scanf("%d%d",&n,&m)==2&&n&&m)的含义:
    第一个数输入的返回值为两个%d, 意思为只有输出两个整数后才返回2。所以 scanf() == 2;&& 的意思为: 不但要输入2个整数int类型的数,还有n且m不等于0。
    意义:无限循环执行while循环。
  2. lower_bound(begin,end,x) :
    lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
  • 从小到大排序:
    lower_bound(begin,end,num ):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
    upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
  • 从大到小排序:
    lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
    upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
  1. sort(v.begin(),v.end()) 从小到大排序。可以给任意对象排序,包括内置类型、自定义类型。

猜你喜欢

转载自blog.csdn.net/JingYan_Chan/article/details/127558988