前言
在我看来,大部分面试的算法题从来都不是难在思维,而是缺乏系统的教学。它不像数学属于普及的基础教育,算法题目的大部分知识、技巧往往都局限于 competitive programming 当中 (比如各种 OI 竞赛、 ACM 竞赛等),这些都是大部分计算机行业从业者接触不到的。它就像一个大群体中一个半封闭的小群体一样,系统的知识就在那里,只是我们很少会主动走进去。因此,我期望将这些知识给带出来,就引申出了本系列文章和视频。
二分法是一种随处可见却又非常精妙的算法,我们最熟知的用法是在一个有序数组中查找某个 target 是否存在。初学二分法的同学可能会被各种边界情况、不同写法、是开区间还是闭区间等细节弄糊涂,以至于舍本逐末。其实并不需要如此,我们只需要记住一种最方便的写法并理解它即可。
二分法主题分为两篇,本篇为第一篇。共涉及到 60 道 题目,以 LeetCode 难度划分属于 hard 和 medium 偏上的题目。
注意:搭配 B 站视频更香奥!
正文
通常我们将二分法分为整数域上的二分和实数域上的二分。 - 整数二分的细节在于终止边界、左右区间取舍时的开闭情况,来避免漏掉答案或者造成死循环。 - 实数二分的细节在于精度问题
因此,本文会分别给出 整数二分 和 实数二分 的模板,来帮助大家解决 90% 以上的广泛二分问题。广泛二分问题指的是如下几种类型: 1. 明显二分问题(题面上能一下看出二分的) 2. 对结果进行二分(值域上二分) 3. min(max()) 和 max(min()) 4. 最大/最小平均值(max/min average) 5. 特殊第 K 小问题
理解了这几种题型,也就能够理解接近 100 道的算法题,基本都是 leetcode hard/medium 级别的。
在给出模板之前,我们得先理解什么是二分?
二分不等价于序列上的单调性。它的本质是:
如果我们能够通过某种特性将一个区间划分成两个区间,左边区间满足某种特性;右边区间不满足某种特性。那么我们就能够通过二分法来寻找左区间的右端点或者右区间的左端点。换句话讲,有单调性一定可以二分,但是二分不一定要有单调性。
更多细节可以在 B 站搜索 《百学原理》 up主,面试向算法系列 - 1.4 二分法的经典应用