3.二分法

二分法(Binary Search)是一种高效的搜索算法,适用于已排序的数组。它的基本思想是在每一步中,将待搜索区间一分为二,并确定目标值可能存在的位置。然后根据目标值与中间元素的大小关系,决定舍弃哪一半的区间,从而将搜索范围缩小一半。重复这个过程,直到找到目标值或者确定目标值不存在为止。  

难点:

1.while()的循环条件能否取等

如果是左闭右闭区间可以取等,有一边是开区间则不能取等

2.right取mid还是mid-1

  • 如果是右闭的区间,值是可以取到的,既然mid已经大于target, 没必要继续加到区间上,所以需要right移动到mid的前一个位置
  • //右开说明取不到mid,直接right取到mid
  • 对于左闭右闭区间 [left,right]
vector<int> arr(1000);
int left = 0;
int right = a.size() - 1;
int target = 1;
while (left <= right) {//左闭右闭区间可以取等号
    int mid = (right - left) / 2;
    if (arr[mid] > target) {
        //由于是右闭的区间,值是可以取到的,既然mid已经大于target,
        //没必要继续加到区间上,所以需要right移动到mid的前一个位置
        right = mid - 1;
    }else if (arr[mid] < target) {
        left = mid + 1;
    }else {
        return mid;
    }
}
return -1;

防止越界写法:int mid = left + (right - left) / 2; 

  • 对于左闭右开区间 [left,right)

//左闭右开区间不可以取等,如[1,1)就是一个不合法的区间,既包含1又不包含1.

int solve() {
    vector<int> a(1000);
    int left = 0;
    int right = a.size();//由于右边不包含边界,所以right=a.size()
    int target = 1;
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (a[mid] > target) {
            //右开说明取不到mid,直接right取到mid
            right = mid;
        }
        else if (a[mid] < target) {
            //左闭说明能取到,此时已经明确a[mid]不会再等于target
            //所以取到mid的下一位
            left = mid + 1;
        }
        else {
            return mid;
        }
    }
    return -1;
}

二分法的妙用

P8647 [蓝桥杯 2017 省 AB] 分巧克力 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 巧妙地使用了二分法来解决这个问题,根据数据的范围来解决该问题,大大降低了效率。

其基本思路是先确定二分的范围为 [1, 10^5],然后通过 check 函数来判断当前的 mid 是否满足条件。如果满足条件,则将左边界 l 更新为 mid,否则将右边界 r 更新为 mid-1。最终得到的 l 即为所求的最大边长。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1e5+10;
int h[N],w[N],n,k;

bool check(int mid){
	int res = 0;
	for(int i=0;i<n;i++){
		res += (h[i]/mid)*(w[i]/mid);
		if(res>=k) return true;
	}
	return false;
}

int main() {
    cin>>n>>k;
    for(int i=0;i<n;i++) scanf("%d%d",&h[i],&w[i]);
	int l=1,r=1e5;
	while(l<r){
		int mid = l+r+1>>1;
		if(check(mid)) l = mid;
		else r = mid-1;
	} 
	cout<<l<<endl;
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值