再学二分法

刷了这么多题发现,二分法经常出现,而且运用范围特别广,就像木棒切割问题,矩阵划分等问题。。所以说二分法是必须熟练掌握的,再看几遍未尝不可;

二分查找高效之处在于每一步都可以去除当前区间中的一半元素,因此其时间复杂度为O(log n)。

木棒切割问题:

给出N根木棒,长度均已知,现在希望通过切割他们来得到至少K段长度相等的木棒,问这些长度相等的木棒最长能有多长。

例:三根长度分别为10,24,15的木棒来说,假设K = 7,既需要至少7段长度相等的木棒,那么可以等到的最大长度为 6.

 思路:

二分查找;每一个长度值 mid 都会对应一个能分割的最大段数 k,然后判断 k 与 K 的大小,前者大:说明长度(mid)小了 -- > 增大left;后者大 :说明长度(mid)大了 -- > 减小right ;

 

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
    int left, right, mid, k, K, N, a[1005];
    scanf("%d",&N);
    for(int i = 0; i < N; i++){
        scanf("%d",&a[i]);
    }
    scanf("%d",&K);
    sort(a, a + N);
    left = 0, right = a[N - 1];
    while(left < right){
        mid = (left + right) / 2;//如果left + right 超 int可以写成,left + (right - left)/ 2; 
        k = 0;
        for(int i = 0; i < N; i++){
            k += a[i] / mid; 
        }
        if(k < K)    right = mid;
        else        left = mid + 1;
    }
    printf("%d\n",right - 1);


    return 0;
}

经典问题模板:

(1)查找 X 。

int binarySearch(int A[], int left, int right, int x){
    int mid;
    while(left <= right){
        mid = (left + right) / 2;
        if(A[mid] == x) return mid;
        if(A[mid] > x)  right = mid - 1;
        else            left = mid + 1;
    }
    return -1;
} 

  

 

(2)查找第一个大于等于 X 元素的位置。

int lower_bound(int A[], int left, int right, int x){
    int mid;
    while(left < right){
        mid = (left + right) / 2;
        if(A[mid] >= x)  right = mid;
        else            left = mid + 1;
    }
    return left;
} 

 

(3)查找第一个大于 X 元素的位置。

int upper_bound(int A[], int left, int right, int x){
    int mid;
    while(left < right){
        mid = (left + right) / 2;
        if(A[mid] > x)  right = mid;
        else            left = mid + 1;
    }
    return left;
} 

 

 

 

posted @ 2021-06-28 10:41  荣荣荣荣荣荣  阅读(89)  评论(0)    收藏  举报