第一个错误的版本[抽象二分入门]

153 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,第一个错误的版本[抽象二分入门] - 掘金 (juejin.cn)

前言

抽象二分,第一需要将问题转换为二分问题(主要是利用其二分夹逼寻找特性),第二需要将二分规则抽象,即high/low的下一次取值是多少?是自增?还是取mid?还是取mid + 1?问题的复杂性和这两点的隐式程度有关。

一、第一个错误的版本

image.png

二、抽象二分

/* The isBadVersion API is defined in the parent class VersionControl.
      boolean isBadVersion(int version); */

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        // 抽象二分寻找有序版本的target版本  -> 第一个错误版本,即寻找第一个true!。
        // 寻找第一个true,不同于普通的二分寻找,找到low <= high,而是通过二分夹逼思想low < high
        int low = 1,high = n;
        while(low < high){
            int mid = low + (high - low >>> 1);

            boolean mark = isBadVersion(mid);
            /*
            if(mark) high = mid;
            if(!mark) low = mid + 1;
            */
            high = mark ? mid : high;
            low  = mark ? low : mid + 1;
        }
        return low;
    }
}

总结

1)抽象二分,第一将问题抽象为二分夹逼,第二将问题的规则抽象出来。抽象二分的难易程度就和两步的隐式程度有关。

2)二分其实有两种,主要体现在二分寻找和二分夹逼,代码体现在low <= high 和 low < high,二分夹逼稍难,也是抽象的考察点。二分夹逼应用在抽象二分/二分插入/二分寻找相同值的左边界或者右边界,这都需要夹逼来寻找。

参考文献

[1] LeetCode 第一个错误的版本