记住这两个二分模板，秒杀所有二分查找算法题！

2021/09/07 09:04

boolean check(int x) {}int search(int left, int right) {    while (left < right) {        int mid = (left + right) >> 1;        if (check(mid)) {            right = mid;        } else {            left = mid + 1;        }    }    return left;}

boolean check(int x) {}int search(int left, int right) {    while (left < right) {        int mid = (left + right + 1) >> 1;        if (check(mid)) {            left = mid;        } else {            right = mid - 1;        }    }    return left;}

1.写出循环条件：while (left < right)，注意是 left < right，而非 left <= right2.循环体内，先无脑写出 mid = (left + right) >> 13.根据具体题目，实现 check() 函数（有时很简单的逻辑，可以不定义函数），想一下究竟要用 left = mid 还是 right = mid4.如果 left = mid，那么无脑写出 else 语句 right = mid - 1，并且在 mid 计算时补充 +1，即 mid = (left + right + 1) >> 15.如果 right = mid，那么无脑写出 else 语句 left = mid，并且不需要更改 mid 的计算；6.循环结束时，left 与 right 相等。

题目解析

题目 1：第一个错误的版本

给定 n = 5，并且 version = 4 是第一个错误的版本。调用 isBadVersion(3) -> false调用 isBadVersion(5) -> true调用 isBadVersion(4) -> true所以，4 是第一个错误的版本。

/* The isBadVersion API is defined in the parent class VersionControl.*/boolean isBadVersion(int version);public class Solution extends VersionControl {    public int firstBadVersion(int n) {        int left = 1, right = n;        while (left < right) {            int mid = (left + right) >>> 1;            if (isBadVersion(mid)) {                right = mid;            } else {                left = mid + 1;            }        }        return left;    }}

题目 2：在排序数组中查找数字

输入: nums = [5,7,7,8,8,10], target = 8输出: 2

输入: nums = [5,7,7,8,8,10], target = 6输出: 0

0 <= 数组长度 <= 50000

class Solution {    public int search(int[] nums, int target) {        if (nums.length == 0) {            return 0;        }        // find first position        int left = 0, right = nums.length - 1;        while (left < right) {            int mid = (left + right) >>> 1;            if (nums[mid] >= target) {                right = mid;            } else {                left = mid + 1;            }        }        if (nums[left] != target) {            return 0;        }        int l = left;        // find last position        right = nums.length - 1;        while (left < right) {            int mid = (left + right + 1) >>> 1;            if (nums[mid] <= target) {                left = mid;            } else {                right = mid - 1;            }        }        return left - l + 1;    }}

题目 3：爱吃香蕉的珂珂

输入: piles = [3,6,7,11], H = 8输出: 4

输入: piles = [30,11,23,4,20], H = 5输出: 30

输入: piles = [30,11,23,4,20], H = 6输出: 23

class Solution {    public int minEatingSpeed(int[] piles, int h) {        int mx = 0;        for (int pile : piles) {            mx = Math.max(mx, pile);        }        int left = 1, right = mx;        while (left < right) {            int mid = (left + right) >>> 1;            int s = 0;            for (int pile : piles) {                s += (pile + mid - 1) / mid;            }            if (s <= h) {                right = mid;            } else {                left = mid + 1;            }        }        return left;    }}

题目 4：在 D 天内送达包裹的能力

输入：weights = [1,2,3,4,5,6,7,8,9,10], D = 5输出：15解释：船舶最低载重 15 就能够在 5 天内送达所有包裹，如下所示：第 1 天：1, 2, 3, 4, 5第 2 天：6, 7第 3 天：8第 4 天：9第 5 天：10请注意，货物必须按照给定的顺序装运，因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。

输入：weights = [3,2,2,4,1,4], D = 3输出：6解释：船舶最低载重 6 就能够在 3 天内送达所有包裹，如下所示：第 1 天：3, 2第 2 天：2, 4第 3 天：1, 4

1 <= D <= weights.length <= 500001 <= weights[i] <= 500

class Solution {    public int shipWithinDays(int[] weights, int days) {        int left = 1, right = Integer.MAX_VALUE;        while (left < right) {            int mid = (left + right) >> 1;            if (check(weights, days, mid)) {                right = mid;            } else {                left = mid + 1;            }        }        return left;    }    private boolean check(int[] weights, int days, int capacity) {        int cnt = 1, t = 0;        for (int w : weights) {            if (w > capacity) {                return false;            }            if (t + w <= capacity) {                t += w;            } else {                t = w;                ++cnt;            }        }        return cnt <= days;    }}

0 评论
0 收藏
0