排序问题上机考试刷题

本文介绍了查找算法的重要性,特别是二分查找,它在已排序数据中的高效性,以及与线性查找的对比。通过实例演示了二分查找的实现和其在多次查找中的优势。
摘要由CSDN通过智能技术生成

查找是另一类必须掌握的基础算法,它不仅会在机试中直接考查,而且是其他某些算法的基础。排序的重要意义之一便是帮助人们更加方便地进行查找。如果不对数据进行排序,那么在查找某个特定的元素时,需要依次检查所有的元素,这样的方式对于单次或少量的查找来说运行效率是很高的,但查找次数较多时,如果所有元素都是有序的,那么就能更快地进行检索,而不必逐个元素地进行比较。

例题一:

找x_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=N7T8https://www.nowcoder.com/practice/069e2130430c41229ab25e47fa0949a6?tpId=40&tqId=21489&tPage=1&rp=1&ru=/ta/kaoyan&qru=/ta/kaoyan/question-ranking解析:

#include<iostream>
using namespace std;

int main()
{
	int arr[200] = { 0 };
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> arr[i];
	}
	int x;
	cin >> x;
	int flag = 0;//设置标志位
	for (int i = 0; i < n; i++)
	{
		if (arr[i] == x)
		{
			flag = 1;//说明找到了x
			cout << i;
			break;
		}
	}
	if (flag == 0)
	{
		cout << -1;
	}

	return 0;
}

 下面介绍一种不同于线性查找的查找策略,而是一种策略性、跳跃性的方法来遍历查找空
间,它就是二分查找。二分查找建立在待查找元素排列有序的前提下。假设元素是按升序排列的,将序列中间位置记录的关键字与查找关键字比较,若二者相等,则查找成功;否则利用中间位置记录的关键字将序列分成前、后两个子序列,若中间位置记录的关键字大于查找关键字,则进一步查找前面的子序列,否则进一步查找后面的子序列。重复以上过程,直到找到满足条件的记录(查找成功),或到子序列不存在为止(此时查找不成功)。
由于每次查找都会舍弃一半的元素,因此二分查找的时间复杂度可由线性查找的 O(n)降至
O(logn)。有的读者可能会有疑问,虽然二分查找的时间复杂度要低于线性查找,但排序的时
间复杂度至少是 O(nlogn),如此说来线性查找岂不是要优于二分查找?如果只要求对序列进行单次查找,那么线性查找不失为一个好策略,但如果要进行多次查找,那么线性查找将不再具有优势。假设查找次数为 m,那么线性查找的时间复杂度为 O(nm),二分查找的时间复杂度为O(nlogn + mlogn),可见当 m 特别小时线性查找很有优势,但当 m 大到一定程度时,二分查找的性能便会远远优于线性查找。

例题二:

查找_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=N7T8https://www.nowcoder.com/practice/d93db01c2ee44e8a9237d63842aca8aa?tpId=40&tqId=21531&tPage=1&rp=1&ru=/ta/kaoyan&qru=/ta/kaoyan/question-ranking

思路:

代码:
方法一:

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

bool Binary_search(int data, int arr[], int n)
{
	int left = 0, right = n - 1;
	while (left <= right)//循环条件非常容易写错
	{
		int mid = (left + right) / 2;//这一句话很容易出错,left+right记得带上括号
		if (arr[mid] == data)
		{
			return true;
		}
		else if (arr[mid] > data)
		{
			right = mid - 1;
		}
		else
		{
			left = mid + 1;
		}
	}
	return false;
}
int main()
{
	int n;
	cin >> n;
	int arr[100] = { 0 };
	for (int i = 0; i < n; i++)
	{
		cin >> arr[i];
	}
	sort(arr, arr + n);
	int m;
	cin >> m;
	for (int i = 0; i < m; i++)
	{
		int data;
		cin >> data;
		bool exist = Binary_search(data, arr, n);
		if (exist)
		{
			cout << "YES" << endl;
		}
		else
		{
			cout << "NO" << endl;
		}
	}

	return 0;
}

注意:此处在刷OJ题目时,一般建议把arr数组设置为全局的数组,这样就可以在调用二分查找函数时不用把arr数组传参过去,以免防止传参设置错误的情况.

方法二:

 map的find函数,如果查找成功会返回对应位置元素的迭代器,如果查找失败,会返回最后一个元素的后一个位置的指针.

#include<map>
#include<iostream>
using namespace std;
int main()
{
	int n;
	cin >> n;
	int arr[100] = { 0 };
	map<int, int> Find_Index;//map的底层是一个二叉搜索树,查找效率非常高
	for (int i = 0; i < n; i++)
	{
		cin >> arr[i];//依旧还是把元素放入arr数组中
		Find_Index[arr[i]] = i;//注意这一步
		//将数组的元素作为键,数组元素的下标作为值,插入到map中
	}
	int m;
	cin >> m;
	for (int i = 0; i < m; i++)
	{
		int data;
		cin >> data;

		if (Find_Index.find(data) == Find_Index.end())//find函数会返回找到那个元素的迭代器
		{
			cout << "NO" << endl;
		}
		else
		{
			cout << "YES" << endl;
		}
	}

	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~|Bernard|

你的鼓励是我写下去最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值