蓝桥杯:C++二分算法

这篇具有很好参考价值的文章主要介绍了蓝桥杯:C++二分算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在基本算法中,二分法的应用非常广泛,它是一种思路简单、编程容易、效率极高的算法。蓝桥杯软件类大赛中需要应用二分法的题目很常见。

二分法有整数二分和实数二分两种应用场景

二分法的概念

二分法的概念很简单,每次把搜索范围缩小为上一次的1/2,直到找到答案为止。

二分法的效率很高,只需计算log(n)次。

下面介绍二分法的模板代码bin_search()函数:

我们用猜数字的例子,先给数组初始化,然后定义你要猜的数,用二分法效率高。

对于二分法的讲解非常细致,都在注释中。

#include<bits/stdc++.h>
using namespace std;
int a[1000];
int bin_search(int *a, int n, int x) {   //在数组a中查找数字x,返回位置
	int left = 0, right = n;	//left 通常初始化为 0,表示搜索范围的左边界是数组的第一个元素;right通常初始化为 n(数组的长度),表示搜索范围的右边界是数组的最后一个元素的下一个位置。
	while (left < right) {
		int mid = left+(right-left)/2;   //mid的标准写法,建议这样写,不能用(left+right)/2,有可能会整数溢出的。 
		if (a[mid] >= x) right = mid;   //x小,在左边,把右边的一半砍掉,这里就不用加1了,我们本身就是大于等于x。 
		else             left = mid+1;	//加1的原因是我们要跳过 a[mid] 这个元素,因为它小于 x,我们要的是等于x的元素 
		cout<<a[mid]<< " ";              //输出猜数的过程    如果你想省略过程,可以注释掉这一行的输出语句。 
	}
	return left;    //返回left所在的索引,不要牵扯到right,避免混淆,right一开始是索引的下一个位置。 
}
int main() {
	int n = 100;
	for(int i=0; i<n; i++) a[i]=i+1;    //赋值,数字1~100
	int test = 54;                      //猜54这个数
	int pos = bin_search(a,n,test);
	cout<<"\n"<<"test="<<a[pos];    
}

bin_search()有3个重要点:区间左端点left、区间右端点right、二分的中位数mid。每次把区间缩小一半,把left或right移动到mid;直到left = right为止,即找到答案所处的位置。

二分法的作用:

二分法可以把一个长度为n的有序序列上O(n)的查找时间优化到O(logn)。

注意应用二分法的前提:序列是有序的,按从小到大或从大到小排序。

无序的序列无法二分,如果是无序的序列,则应该先排序再对其进行二分,先排序再二分,排序的复杂度是O(nlog2(n)),二分的复杂度是O(log2(n))。排序加二分的总复杂度是O(nlog2(n))。如果使用暴力法,直接在无序的n个数里面查找,最多查找n次,复杂度是O(n)的,比先排序再二分快。如果不是查找一个数,而是查找m个数,那么先排序再做m次二分的计算复杂度是O(nlog2(n)+ mlog2(n)),而暴力法的复杂度是O(mn),此时二分法远好于暴力法。

整数二分

在单调递增序列中查找x或者x的后继:

前面介绍的bin_search()函数就是“在单调递增序列中查找x或者x的后继”的模板代码。

二分函数都是一摸一样的,测试数据可以改一下,看看能不能查找后继:

int main() {
	int n = 100;
	for(int i=0; i<n; i++) a[i]=2*i+2;    //赋值,数字2~200,偶数
	int test = 55;                        //查找55或55的后继
	int pos = bin_search(a,n,test);
	cout<<"test="<<a[pos];//56   55没有,只能找56了。
}

在单调递增序列中查找x或者x的前驱:

#include<bits/stdc++.h>
using namespace std;
int a[1000];
int bin_search2(int *a, int n, int x) {
	int left = 0, right = n;
	while (left < right) {
		int mid = left + (right-left + 1)/2 ;   //+1是为了确保在 left 和 right 之间的元素数量是奇数时,mid 会指向中间元素;当元素数量是偶数时,mid 会指向中间两个元素的右侧那个元素。
		//这样做的原因是,我们希望在存在重复元素时,mid 尽可能向右偏移,从而找到最右侧的那个等于或小于 x 的元素。
		if (a[mid] <= x)  left = mid;
		else  right = mid - 1;
	}
	return left;
}
int main() {
	int n = 100;
	for(int i=0; i<n; i++) a[i]=2*i+2;   //赋值,数字2~200,偶数
	int test = 55;                       //查找55或55的前驱
	int pos = bin_search2(a,n,test);
	cout<<"test="<<a[pos]; //54
}

整数二分例题

例题1.分巧克力

2017年(第八届)省赛,lanqiaoOJ题号99

蓝桥杯:C++二分算法,蓝桥杯c++,蓝桥杯,c++,算法,数据结构,c语言

先试试暴力法:从边长为1开始到最大边长d,每个值都试一遍,一直试到刚好够分的最大边长为止。编程思路:边长初始值d = 1,然后d = 2、3、4……一个一个地试 。

代码:

#include<bits/stdc++.h>
using namespace std;
int h[100010],w[100010];//多申请10个空间 
int n,k;
bool check(int d) {             //检查够不够分
	int num=0;
	for(int i=0; i<n; i++)  num += (h[i]/d)*(w[i]/d);//假如,将6×5的巧克力的长边(6个单位)和宽边(5个单位)分别除以2×2的小正方形的边长(2个单位)。
	//这样可以得到长边可以切出3个2×2的巧克力,宽边可以切出2个2×2的巧克力。
	//接着,将长边和宽边切出的巧克力块数相乘,即3(长边切出的块数)× 2(宽边切出的块数)= 6。所以,一块6×5的巧克力可以切出6块2×2的巧克力。
	if(num>=k) return true;     //够分
	else       return false;    //不够分
}
int main() {
	cin >>n>>k;
	for(int i=0; i<n; i++)  cin>>h[i]>>w[i];  //长宽各自存在各自的数组中 
	int d=1;                    //正方形边长
	while(1) {
		if(check(d))  d++;      //边长从1开始,一个一个地试
		else          break;
	}
	cout << d-1;
	return 0;     //暴力求解只能过75的测试数据 ,最后两个测试数据错了,暂时不知道什么原因
}

整数二分法求解:

#include<bits/stdc++.h>
using namespace std;
int n,k;
const int N=100010;
int h[N],w[N];
bool check(int d) {
	int num=0;
	for(int i=0; i<n; i++)  num += (h[i]/d)*(w[i]/d);
	if(num>=k) return true;      //够分
	else       return false;     //不够分
}
int main() {
	cin >> n >> k;
	for(int i=0; i<n; i++)   cin>>h[i]>>w[i];
	int L=1, R=N;                //R的初值是100010
	//第一种写法:
	while(L<R) {
		int mid=(L+R+1) / 2;      //除以2,向右取整      不会整数溢出,直接L+R
		if(check(mid))  L=mid;   //新的搜索区间是右半部分,R不变,调整L=mid
		else            R=mid-1; //新的搜索区间是左半部分,L不变,调整R=mid–1
	}
	cout << L;
	//第二种写法:
	/*  while(L<R) {
	        int mid=(L+R) / 2;        //除以2,向左取整   不会整数溢出,直接L+R
	        if(check(mid)) L=mid+1;  //新的搜索区间是右半部分,R不变,更新L=mid+1
	        else           R=mid;    //新的搜索区间是左半部分,L不变,更新R=mid
	    }
	    cout << L-1;    */
	return 0;
}

实数二分

与整数二分相比,实数二分的编程就容易多了,不用考虑整数的取整问题。实数二分的模板代码如下。文章来源地址https://www.toymoban.com/news/detail-826170.html

const double eps = 1e-7;                    //精度。
while(right - left > eps) {                 
	double mid = left+(right-left)/2;
	if (check(mid)) right = mid;          //判定,然后继续二分,check(mid)为true执行此语句
	else            left  = mid;
}

到了这里,关于蓝桥杯:C++二分算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构和算法之二分法查找

    二分法查找,也称作 二分查找 或 折半查找 ,是一种在有序数组中快速查找特定元素的算法。它采用分治法思想,通过将问题划分为规模更小的子问题,并且通过对子问题的查找来解决原问题。 二分法查找的思路是不断地将数组一分为二,然后判断目标值在哪一部分,进而

    2024年02月09日
    浏览(48)
  • 【数据结构与算法】python实现二分查找

    二分查找 又称折半查找,它是一种效率较高的查找方法 原理:首先,假设表中元素是按升序排列,将表中间位置记录的与查找比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的大于查找,则

    2024年02月05日
    浏览(40)
  • 蓝桥杯:C++二分算法

    在基本算法中,二分法的应用非常广泛,它是一种思路简单、编程容易、效率极高的算法。蓝桥杯软件类大赛中需要应用二分法的题目很常见。 二分法有整数二分和实数二分两种应用场景 二分法的概念很简单,每次把搜索范围缩小为上一次的1/2,直到找到答案为止。 二分法

    2024年02月19日
    浏览(45)
  • 【C++】数据结构与算法:常用排序算法

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍常用排序算法。 学其所用,用其所学。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 排序算法是计算机科学中常见的一类算法,用于将一组数据按照特定的顺序进行排

    2024年02月14日
    浏览(49)
  • 【数据结构与算法C++实现】3、排序算法

    原视频为左程云的B站教学 外层循环 :n个数需要冒n-1个泡上去,剩下的一个必然是最小的。所以外层循环执行n-1轮 内层循环 :比大小,第1个泡需要比n-1次,第2个泡,比较n-2次… 选择: 每次从待排序序列中选择 最小的一个 放在已排序序列的后一个位置 原理类似于对扑克牌

    2024年02月11日
    浏览(58)
  • 数据结构——排序算法(C语言)

    本篇将详细讲一下以下排序算法: 直接插入排序 希尔排序 选择排序 快速排序 归并排序 计数排序 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某写的大小,按照递增或递减0排列起来的操作。 稳定性的概念 假定在待排序的记录序列中,存在多个

    2024年02月08日
    浏览(66)
  • C语言数据结构与算法

    冒泡排序 例题 顺序表下的 冒泡排序 注意:冒泡排序 稳定,最多执行n(n-1)/2次 选择排序不稳定,平均比较次数n(n-1)/2 直接插入排序,是在有序基础上,速度最快且稳定的排序方法。 希尔排序是 不稳定的 顺序查找 二分查找(非递归) 二分查找(递归) 数组 链表 查询 快 慢

    2024年02月06日
    浏览(74)
  • C++基础-介绍·数据结构·排序·算法

    C++是一门风格严谨又不失自由的开发语言,提供了完整的内存管理、支持函数式编程和面向对象编程,支持模板、多继承、多实现、重载、重写等多态特性。 优势在于目前90%的操作系统、数据库、应用基础架构、硬件嵌入式等都是使用C/C++制作的,而C++是对C的标准扩展,掌握

    2024年02月03日
    浏览(45)
  • C++数据结构与算法——哈希表

    C++第二阶段——数据结构和算法,之前学过一点点数据结构,当时是基于Python来学习的,现在基于C++查漏补缺,尤其是树的部分。这一部分计划一个月,主要利用代码随想录来学习,刷题使用力扣网站,不定时更新,欢迎关注! 给定两个字符串 s 和 t ,编写一个函数来判断

    2024年02月19日
    浏览(58)
  • C++数据结构与算法——栈与队列

    C++第二阶段——数据结构和算法,之前学过一点点数据结构,当时是基于Python来学习的,现在基于C++查漏补缺,尤其是树的部分。这一部分计划一个月,主要利用代码随想录来学习,刷题使用力扣网站,不定时更新,欢迎关注! 请你仅使用两个栈实现先入先出队列。队列应当

    2024年02月20日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包