携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,第一个错误的版本[抽象二分入门] - 掘金 (juejin.cn)
前言
抽象二分,第一需要将问题转换为二分问题(主要是利用其二分夹逼寻找特性),第二需要将二分规则抽象,即high/low的下一次取值是多少?是自增?还是取mid?还是取mid + 1?问题的复杂性和这两点的隐式程度有关。
一、第一个错误的版本
二、抽象二分
/* 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,二分夹逼稍难,也是抽象的考察点。二分夹逼应用在抽象二分/二分插入/二分寻找相同值的左边界或者右边界,这都需要夹逼来寻找。