二分查找刷题1

本文作者分享了在研究生阶段如何通过阅读《图解算法》和《深入浅出程序设计竞赛--基础篇》来学习和刷题,特别关注了二分查找算法,包括处理目标值存在相同元素时的特殊情况。作者还提供了C++代码示例,展示了如何在实际编程竞赛中使用二分查找。
摘要由CSDN通过智能技术生成

本人目前在一所普通高校研究生在读,写笔记的目的是为了记录下自己刷题的内容,方便日后观看。

参考书目:《大话数据结构》------程杰

                  《图解算法》---------袁国忠译

                 《深入浅出程序设计竞赛--基础篇》------汪楚奇

本文结合《图解算法》的书作为参考,第一章涉及到二分查找的内容,再针对性的对二分查找刷题。练习的题目来源《深入浅出程序设计竞赛--基础篇》,本文将按照自己做题的思路以及书上例子的参考源码做笔记。

                      

                                                      图1 节选自《图解算法》

               

                                            图2  节选自《深入浅出程序设计竞赛--基础篇》

 此书题目可在洛谷中查找【深基13.例1】查找 - 洛谷

此题是标准的二分查找求解,需要注意的是,当找到的目标值存在相同的元素时,要进行特殊处理,题目的要求是找到相同元素中的第一个元素的下标位置,所以找到目标函数时还要判断其是否为首位元素,用right = mid - 1; 向左搜索即可。

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

class BinarySearch
{
public:
	static int search(const vector<int>& nums, int target)
	{
		int left = 0;
		int right = nums.size() - 1;
		int result = -1; // 初始化结果为-1
		while (left <= right)
		{
			int mid = left + (right - left) / 2;
			if (nums[mid] > target)
			{
				right = mid - 1;
			}
			else if (nums[mid] < target)
			{
				left = mid + 1;
			}
			else
			{
				result = mid; // 找到一个目标值
				right = mid - 1; // 继续向左搜索第一个出现的位置
			}
		}
		// 如果找到目标值,返回索引+1(为了符合从1开始的索引)
		return result == -1 ? -1 : result + 1;
	}
};
int main()
{
	int n, m;
	cin >> n >> m;
	vector<int>nums(n);
	for (int i = 0; i < n; i++)
	{
		cin >> nums[i];
	}
	vector<int>targets(m);
	int target;
	for (int j = 0; j < m; j++) {
		cin >> target;
		// 对每个目标值调用search函数并打印结果
		cout << BinarySearch::search(nums, target) << ' ';
	}
	cout << endl;
	return 0;
}

 下面的示例是书上的代码,这个代码的缺点是没有考虑到存在相同元素的情况,需要返回的是第一个出现的位置。

#include<iostream>
#define MAXN 1000010
using namespace std;

int a[MAXN], m, n, q;
int find(int x)
{
	int l = 1, r = n;//从下标1开始
	while (l <= r)
	{
		int mid = (l + r) / 2; //查找的中间位数
		if (a[mid] == x) return mid;  //找到需要的数字
		else if (a[mid] > x) r = mid - 1; //取区间前一半
		else l = mid + 1; //取区间后一半
	}
	return -1; //没找到返回-1
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
	}
	for (int i = 0; i < m; ++i)
	{
		cin >> q;
		cout << find(q) << " ";
	}
	return 0;
}

下面是书中修改后的代码,考虑了重复元素的情况。(注:代码改变的是find函数的内容)

int find(int x)
{
	int l = 1, r = n+1;//从下标1开始,
	while (l < r)    //最后l和r会相等,左闭右开形式
	{
		int mid = l +( r-1) / 2; //查找的中间位数,避免运算溢出
		if (a[mid] >=x) r = mid; //取区间前一半
		else l = mid + 1; //取区间后一半
	}
	if (a[l] == x)return 1; //
	else return -1; //没找到返回-1
}

                          图3 节选自《深入浅出程序设计竞赛--基础篇》-二分查找步骤

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值