二分模板(整数二分,浮点二分)

二分是经常使用的方法,等抽时间总结一下二分的遇到的题目。注意,二分并不一定要求序列要有序,只要序列满足某种特定的特征即可。
二分的模板有两种:
一种是:找大于等于给定数的第一个位置(满足条件的第一个数)
一种是:找小于等于给定数的最后一个数(满足条件的最后一个数字)
在这里插入图片描述

https://www.acwing.com/blog/content/346/

二分的基本流程如下:

  • 确定二分的边界
  • 设计一个check函数,能够进行二分的判定方法
  • 判断一下区间该如何更新 如果更新的方式是l=mid,r =
    mid-1,那么在计算mid 的时候需要加1

在以下的题目中 [l,r] 指的是闭区间,这下就知道初始 l 和 r 如何取值了。

bool check(int mid){ …… return ……;}
//模板一 找满足某个条件的第一个数  即右半段
int binary1(int l, int r)
{
	while(l<r)
	{
		int mid=(r+l)>>1;
		if(check(mid) r=mid;
		else l=mid+1;
	}
	return l;
}
//模板二  找满足某个条件的最后一个数  即左半段
int binary1(int l, int r)
{
	while(l<r)
	{
		int mid=(r+l+1)>>1;
		if(check(mid) l=mid;
		else r=mid-1;
	}
	return l;
}

例题一
题目描述
实现函数 int sqrt(int x),计算并返回x的平方根(向下取整)

此时的 r = x/2,不需要设置为 x。还需要注意的是在求解mid的时候,如果输入的数据很大的时候,l 和 r 相加会出现溢出,因此需要将 (l+r)的范围扩大到 long long 类型,然后再进行除以2操作,最后将mid 转化为 int 类型。

class Solution {
public:
    /**
     * 
     * @param x int整型 
     * @return int整型
     */
    int sqrt(int x) {
        // write code here
        int l=1,r=x/2;
        if(x<2) return x;
        while(l<r)
        {
            int mid=(l+r+1ll)>>1;
            if(mid<=x/mid) l=mid;
            else r=mid-1;
        }
        return l;
    }
};

注意:上述模板只是针对二维数组中寻找存在的数字提出的模板,例题中需要针对相应的要求进行修改,比如例题一:如果给定的数字不在序列中的话需要用 找到的数组位置处的数字与目标值做比较,如果相等则返回该位置坐标,如果不相等按照题目要求返回应该要求的数字。

例题二
题目描述
请实现无重复数字的升序数组的二分查找
给定一个 元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @param target int整型 
     * @return int整型
     */
    int search(vector<int>& nums, int target) {
        // write code here
        if(!nums.size()) return -1;
        int l=0,r=nums.size()-1;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(nums[mid]>=target) r=mid;
            else l=mid+1;
        }
        if(nums[l]==target) return l;
        else return -1;
    }
};
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l=0,r=nums.size()-1;
        while(l<r)
        {
            int mid=(l+r+1)>>1;
            if(nums[mid]<=target) l=mid;
            else r=mid-1;
        }
        return nums[l]==target?l:-1;
    }
};

例题3:数的三次方根(浮点二分)

#include<iostream>
using namespace std;
double n;
bool check(double mid)
{
    if(mid*mid*mid>=n) return true;
    else return false;
}
int main()
{
    cin>>n;
    double l=-10000,r=10000;
    for(int i=0;i<100;i++)
    {
        double mid=(l+r)/2.0;
        if(check(mid)) r=mid;
        else l=mid;
        
    }
    
    printf("%.6f",l);
    return 0;
    
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值