二分&三分算法

二分算法模板

边界要求:二分答案时,我们最终的答案是由mid进行判定,然后通过移动l或r来缩小范围。当我们的数据中所有的数据都无法使l进行移动,l指向一个未定值(-1)表示l没有用到。所以,我们二分模板中的l, r分别指向L - 1, R + 1。

while(l + 1 < r) {

  int mid = l + r >> 1;

  if(check(mid)) l = mid;

  else r = mid;

}

 

三分算法最后的答案是min(f(l), f(l + 1), f(r)) 或者 min(f(l), f(r)) 我们不能使l或r处于未定态及不能有 L - 1, R + 1 这种越界下标存在。所以l = L, r = R即可。

三分算法模板1: 由二分算法变过来, 长得和二分模板像,当 l = m1的时候,范围缩减1/2 反之缩减1/4

            l, r = 0, 99999
            while l + 1 < r:
                m1 = (l + r) // 2
                m2 = (m1 + r) // 2
                f1 = cost(m1, flag)
                f2 = cost(m2, flag)
                if f1 > f2:
                    l = m1
                else:
                    r = m2

三分算法模板2: 字面意义上的三分,每次左侧右侧都是缩减1/3

        def search(flag: int) -> int:
            l, r = 0, 99999
            while l + 2 < r:
                m1 = (l * 2 + r) // 3
                m2 = (l + r * 2) // 3
                f1 = cost(m1, flag)
                f2 = cost(m2, flag)
                if f1 > f2:
                    l = m1
                else:
                    r = m2

 

 

 

 

class Solution {
public:
    int findRadius(vector<int>& houses, vector<int>& heaters) {
        int n = houses.size(), m = heaters.size();

        sort(houses.begin(), houses.end());
        sort(heaters.begin(), heaters.end());

        auto check = [&](int rid) -> bool {
            for(int i = 0, j = 0; i < n; i ++ ) {
                while(j < m && houses[i] > heaters[j] + rid) j ++ ;
                if(j < m && heaters[j] - rid <= houses[i] && heaters[j] + rid >= houses[i]) continue;
                return false;
            }
            return true;
        };

        int l = -1, r = 1e9;
        while(l + 1 < r) {
            int mid = l + r >> 1;
            if(check(mid)) r = mid;
            else l = mid;
        }

        return r;
    }
};

 

 

 

class Solution {
public:
    int hIndex(vector<int>& citations) {
        sort(citations.begin(), citations.end());
        int n = citations.size();

        int l = -1, r = n + 10;

        auto check = [&](int mid) -> bool {
            int cnt = citations.end() - lower_bound(citations.begin(), citations.end(), mid);
            return cnt >= mid;
        };

        while(l + 1 < r) {
            int mid = l + r >> 1;
            if(check(mid)) l = mid;
            else r = mid;
        }

        return l;

    }
};

 

 

class Solution {
public:
    int minEatingSpeed(vector<int>& piles, int h) {
        int n = piles.size();
        int l = 0, r = *max_element(piles.begin(), piles.end()) + 10;
        auto check = [&](int mid) -> bool {
            long t = 0;
            for(auto it: piles) {
                t += (it + mid - 1) / mid;
            }
            return t <= h;
            
        };

        while(l + 1 < r) {
            int mid = l + r >> 1;
            if(check(mid)) r = mid;
            else l = mid;
        }

        return r;
    }
};

 

posted @ 2023-10-26 12:20  深渊之巅  阅读(31)  评论(0)    收藏  举报