c++二分算法

hello😄

又来发算法了💡(其实早就写完了今天刚发)

这次来发一下「二分」

二分也是比较简单滴

二分查找

二分查找,也就是我们常说的「对半查找法」

这么说你可能不懂,简单说,A和B玩猜数游戏,B想了一个1到100之间的数,不告诉A,A第一次猜50,B说猜小了,A又猜75,B说猜小了,A猜87,B说猜大了,A猜85,B说猜对了

在用二分法进行查找时,查找对象的数组必须是有序的,即各数组元素的次序是按其值的大小顺序存储的。其基本思想是先确定待查数据的范围(可用 [left,right] 区间表示),然后逐步缩小范围直到找到或找不到该记录为止。具体做法是:先取数组中间位置(mid=(left+right)/2)的数据元素与给定值比较。若相等,则查找成功;否则,若给定值比该数据元素的值小(或大),则给定值必在数组的前半部分[left,mid-1](或后半部分[mid+1,right]),然后在新的查找范围内进行同样的查找。如此反复进行,直到找到数组元素值与给定值相等的元素或确定数组中没有待查找的数据为止。因此,二分查找每查找一次,或成功,或使查找数组中元素的个数减少一半,当查找数组中不再有数据元素时,查找失败。
     二分法查找是一种非常高效的搜索方法,主要原理是每次搜索可以抛弃一半的值来缩小范围。其时间复杂度是O(log2n),一般用于对普通搜索方法的优化。题目中若要求算法的时间复杂度是O(logn),那么这个算法基本上就是二分法。
    二分法的适用情况一般满足以下几点:
(1)该数组数据量巨大,需要对处理的时间复杂度进行优化;
(2)该数组已经排序;
(3)一般要求找到的是某一个值或一个位置。
二、分法查找的思路如下:

1:首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
2:如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤1的操作。
3:如果某一步数组为空,则表示找不到目标元素。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkBZUl9U,size_20,color_FFFFFF,t_70,g_se,x_16

 

这就是二分查找。是不是很简单?

看道例题

有若干个数按由小到大的顺序存放在一个一维数组中,输入一个数x,用二分查找法找出x是数组中第几个数组元素的值。如果x不在数组中,则输出“无此数!”。
      (1)编程思路。
      设有一数组a[n],数组中的元素按值从小到大排列有序。用变量low、high和mid分别指示待查元素所在区间的下界、上界和中间位置。初始时,low=0,high=n-1。
      1)令 mid = (low+ high) /2 。
      2)比较给定值x与a[mid]值的大小
      若a[mid] == x ,则查找成功,结束查找;
      若a[mid]> x ,则表明给定值x只可能在区间low ~ mid-1内,修改检索范围。令high=mid-1,low值保持不变;
      若a[mid]< x ,则表明给定值x只可能在区间mid+1~high内,修改检索范围。令low=mid+1,high值保持不变。
      3)比较当前变量low和high的值,若low≤high,重复执行第1)、2)两步,若low>high,表明数组中不存在待查找的元素,查找失败。
      例如,设一有序的数组中有11个数据元素,它们的值依次为{3,8,15,21,35,54,63,79,82,92,97},用二分查找在该数组中查找值为82和87的元素的过程。

代码(如果你刚学还是要自己写的,所以我发图片) 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkBZUl9U,size_20,color_FFFFFF,t_70,g_se,x_16

 再看道例题

编写一个程序计算x的平方根,x保证是一个非负整数。当  right−left<10^−5时结束,此时已经满足精度要求,即为所求的近似值。
      (1)编程思路。
      已求5的平方根为例,说明应用二分法求平方根的思路。
      设  f(x)=x2 ,在 x∈[1,5]的范围内, f(x) 随着 x的增大而增大的(单调递增),这就给二分法创造了条件。
首先,令浮点型 left 和 right 的初值分别为1和5,然后通过比较 left 和 right 的中点 mid 处  f(x) 的数值与5的大小来选择子区间进行逼近。有以下两种情况:
      1)如果  f(mid)>5,说明当前mid比5的平方根大,应当在 [left,mid]的范围内继续逼近,故令  right=mid;
      2)如果 f(mid)<5,说明当前 mid比5的平方根小,应当在 [mid, right]的范围内继续逼近,故令  left=mid。

代码

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkBZUl9U,size_18,color_FFFFFF,t_70,g_se,x_16

 

 

看了上面几道题,其实都是比较简单的。

来一道稍微难点的

跳石头     NOIP2015  提高组
题目背景
一年一度的“跳石头”比赛又要开始了!
题目描述
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。
输入格式
第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L≥1 且 N≥M≥0。
接下来 N 行,每行一个整数,第 i 行的整数 Di​(0<Di​<L), 表示第 i 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。
输出格式
一个整数,即最短跳跃距离的最大值。
输入输出样例
输入 
25 5 2
2
11
14
17
21
输出  
4
说明/提示
输入输出样例 1 说明:将与起点距离为 2和 14 的两个岩石移走后,最短的跳跃距离为 4(从与起点距离 17 的岩石跳到距离 21 的岩石,或者从距离 21 的岩石跳到终点)。
另:对于 20%的数据,0≤M≤N≤10。
对于50%的数据,0≤M≤N≤100。
对于 100%的数据,0≤M≤N≤50,000,1≤L≤1,000,000,000。
 
【解题说明】
20分做法:直接暴力即可
50分做法:考虑DP,f[i][j]表示在前i块石头移走j块石头的最短距离,转移即可
60分做法:考虑贪心,每次删除间距最小的,用堆维护
100分做法:从起点出发,先选定一段距离mid,若前面的石头B与你所站着的石头A的距离小于mid,就把B搬掉,记录一下;如果不,就把B留下,再跳到石头B上。照这个步骤多次循环后,如果搬掉的石头多了,就把距离mid定小点;如果少了,就把mid定大点。
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkBZUl9U,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

除了这些,还有洛谷上木材切割、奶牛一些题可以自己做一做,都不难

最后

你们来帮我看看这几种颜色那种最好看?

1

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkBZUl9U,size_20,color_FFFFFF,t_70,g_se,x_16

2

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkBZUl9U,size_20,color_FFFFFF,t_70,g_se,x_16 

3

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkBZUl9U,size_20,color_FFFFFF,t_70,g_se,x_16 

直接评论数字告诉我即可

拜拜 

 

 

 

 

 

 

  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值