关于几种二分的想法
来源:互联网 发布:java vector实现原理 编辑:程序博客网 时间:2024/04/30 09:50
一般的二分能解决在单调序列中查找某个数是否存在的作用,假如查找的某数有多个,我要你输出第一个的位置,或者最后一个的位置,其实这些问题也能用而二分解决。
c++中貌似自带lower_bound 和upper_bound函数,分别是在单调有序的序列中,找到第一个大于给定值和第一个大于等于给定值的数的位置,但是这些都是怎么实现的呢?
现在有一串单调非递减的序列(意味着有重复数字),那么先说明4个问题:
1 找出这个序列第一个大于给定数字k的位置和那个数,这个数可能出现了好几次,我要找第一次的位置;
2 找出这个序列第一个大于等于给定数字k的位置和那个数,这个数可能出现了好几次,我要找第一次的位置;
3 找出这个序列第一个大于给定数字k的位置和那个数,这个数可能出现了好几次,我要找最后一次的位置;
4 找出这个序列第一个大于等于给定数字k的位置和那个数,这个数可能出现了好几次,我要找最后一次的位置;
3,4两个问题可能表述的不够清楚,这里的意思是,假如这串数中从小到大第一个满足条件的数有好多个,或者说出现了很多次,我要求的是第一个符合条件的最后一次出现的,并不是整串中的最后一个,比如1,2,2,2,3 ,我要找最后一个(第一次)大于等于2的位置,我要求的不是3这个位置,而是最后一个2的位置。
对于问题1,有如下代码:
while(l<r){ int mid=l+(r-l)/2; if(a[mid]>k) r=mid; else if(a[mid]<=k) l=mid+1;}
对于问题2,有如下代码:
while(l<r){ int mid=l+(r-l)/2; if(a[mid]>=k) r=mid; else if(a[mid]<k) l=mid+1;}
最后跳出循环时l=r就是所求的位置。
两者的差距就是取到等号的时候执行的不同的语句,一般来说二分最怕的是死循环,我认为可以从边界考虑,比如从l+1==r,l+2==r,l+3==r这三种情况,会发现这三种情况的任意一种都不会导致死循环,而且第三章情况会变成第一种情况,并且退出循环时,l==r。
那对于问题3和问题4,我们不能直接解决它,但是可以通过二分找两次来解决,
对于问题3,我们先找到第一个大于K的数的位置,设为pos,然后我们再找第一个大于a[pos]这个数的位置,
设为pos2,然后pos2-1就是答案了。
对于问题4,我们先找到第一个大于等于K的数的位置,设为pos3,然后在找第一个大于a[pos3]这个数的位置,
设为pos4,然后pos4-1就是答案了。
其实还有4个类似的问题,现在要找出最后一个出现小于(等于)K的数的第一个位置和最后一个位置。
也可以用差不多的方法解决。
接着来考虑问题5到问题8,
问题5找出这个序列最后一个小于给定数字k的位置和那个数,这个数可能出现了好几次,我要找最后一次的位置;
问题6找出这个序列最后一个小于等于给定数字k的位置和那个数,这个数可能出现了好几次,我要找最后一次的位置;
问题7找出这个序列最后一个小于给定数字k的位置和那个数,这个数可能出现了好几次,我要找第一次的位置;
问题8找出这个序列最后一个小于等于给定数字k的位置和那个数,这个数可能出现了好几次,我要找第一次的位置;
问题5和问题6,其实蛮简单的,只需要将问题2和问题1的位置减去1即可。
即问题2答案-1=问题5答案,问题1答案-1=问题6答案。
对于问题7,可以先找到第一个大于等于K这个数的位置,记为pos5,
然后我再找第一个大于等于a[pos5-1]的位置pos6即为答案。
对于问题8,可以先找到第一个大于K这个数的位置,记为pos7,
然后我再找第一个大于等于a[pos7-1]的位置pos8即为答案。
至此所有问题都解决,二分真是一个给力的东西!
最后还需要说明的一点,我这种二分的写法没办法处理一直特殊情况 ,为了方便理解,之前也没有说明,我代码中的l和r一直代表所能取到的数的闭区间,但是会有有可能,我要找的数它一开始就不在这个区间,比如1,2,3,4,5,我要找第一个大于6的数的位置,我初始化l=0,r=4那么无论如何这个求解结果都是错的,因为根本不存在0到4的范围里有这个数。我想到的一种做法就是,初始化r=5,那么答案是正确的。r初始化的位置本来选取最后一个数的位置,但是为了保证结果的准确,可以初始化为最后一个数的位置+1。
0 0
- 关于几种二分的想法
- 关于使用JSP的几点想法
- 关于以后的几点想法。。。。。。。。。
- 关于用户需求的几点想法
- 关于研发管理的几点想法
- 关于冒泡排序的几点想法
- 关于设计品质保证(DQA)的几点想法
- 关于组建Test Lab的几点想法
- 转载:关于技术积累的几点想法
- 通达OA 关于工作流改进的几点想法
- 关于编写群发软件过程的几点想法
- 关于计算机工作方向的几点想法
- 关于环境建模与并行计算的几点想法
- 关于家用宽带的几点不满与想法
- Java中关于装饰者模式的几点想法
- 关于程序组团队建设的几点想法
- 关于软考高级作文的几点想法
- 关于公司客户端部门的几点想法
- MSSQL如何查看当前数据库的连接数
- Linux stat函数讲解
- HttpClient教程(六)
- VS2013快捷键大全
- 下载android源码
- 关于几种二分的想法
- hibernate.current_session_context_class属性配置
- 获取手机的相关信息
- 四部金融投资经典教材和30部必读的投资学经
- 30字的完美个人简历
- AlarmManager定时器使用(创建与取消)
- 如何有效地报告 Bug
- MyBatis动态连接数据库,动态传入数据库参数
- Unable to start activity ComponentInfo{com.example.customview/com.example.customview.MainActivity}: