UVa 10474 - Where is the Marble?解题报告

读入一行2个数字 N 和 Q, N 表示接下来的 N 行数字为 marbles, Q 表示 N 行数字之后的 Q 行数字为 query. 要求把 N 行 marbles 从小到大排序, 然后输出每个 Q 在 marbles 中的位置.注意是第一次出现的位置。

思路:用快速排序对其进行排序,然后用二分查找查找其第一次出现的位置。

可以用其他的排序和搜索算法。如qsort。

#include <iostream>
#include <cstring>
using namespace std;
void quicksort(int a[], int p, int r);//快速排序
int partition(int a[], int p, int r);//将数组从key分为两边,一边大于key,一边小于key
int bin_search(int a[], int n, int key);//二分查找
int marble[10005], finds[10005];

int main()
{
	//freopen("data.txt", "r", stdin);
	int n, q;
	int cases = 1;
	while (scanf("%d%d", &n, &q) && n)
	{
		for(int i = 0; i < n; i++)
			scanf("%d", &marble[i]);
		for(int i = 0; i < q; i++)
			scanf("%d", &finds[i]);
		quicksort(marble, 0, n - 1);
		
		printf("CASE# %d:\n", cases++);
		for(int i = 0; i < q; i++)
		{
			int y = bin_search(marble, n, finds[i]);
			if(y == -1)
				printf("%d not found\n", finds[i]);
			else
				printf("%d found at %d\n", finds[i], y + 1);
		}
	}
	return 0;
}

int partition(int a[], int p, int r)
{
	int middle = p;//middle记录key位置
	int x = a[r];//让数组的最后一个数作为中间值key,
	for(int j = p; j < r; j++)//利用冒泡的原理将数据分布到key的两边
		if(a[j] < x)
		{
			int temp = a[middle];
			a[middle] = a[j];
			a[j] = temp;
			middle++;
		}
	int temp = a[r];
	a[r] = a[middle];
	a[middle] = temp;//让key值居中
	return middle;
}
void quicksort(int a[], int p, int r)
{
	if(p < r)//当p=r时,说明排序完成
	{
		int q = partition(a, p, r);
		quicksort(a, p, q - 1);
		quicksort(a, q + 1, r);
	}
}
int bin_search(int a[], int n, int key)
{
	int left = 0,
		right = n - 1,
		flag = -1,
		middle;
	while (left <= right)
	{
		middle = left + (right - left) / 2;//防止(left+right)/2越界
		if(a[middle] == key)
		{
			flag = middle;
			right = middle - 1;//查找key第一次出现的位置,很巧妙的技巧
			//如果要查找key最后一次出现的位置,left = middle + 1
		}
		if(a[middle] < key)
			left = middle + 1;
		if(a[middle] > key)
			right = middle - 1;
	}
	if(flag == -1)
		return -1;
	else
		return flag;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值