二分法
二分法体现了一种“分治”的思想。
二分查找#
当需要在一个数组中查找某个元素的时候,我们自然而然地想到遍历整个数组,找到想要的元素就停止查找。这种方法的时间复杂度是O(n),那么有没有一种更高效一点的方法呢?这时候就轮到二分查找登场了,二分查找的时间复杂度是O(logn),显然是更高效的做法。不过使用二分查找需要有一个前提:数组必须是有序的。因为二分查找是通过比较来进行提速的,如果数组是乱序,或者元素无法进行比较,显然二分查找也就失效了。
int find(vector<int>& nums, int begin, int end, int target)
{
if(begin > end) {
return -1;
}
int mid = (end - begin) / 2 + begin;
if(target == nums[mid]) {
return mid;
}
return target < nums[mid] ? find(nums, begin, mid - 1, target) :
find(nums, mid + 1, end, target);
}
上面代码是一种二分查找的递归实现,begin
表示要查找的开始位置,end
表示要查找的最后位置,如果begin
大于end
,显然整个元素就不在数组中,返回-1表示没有找到。
计算中间位置,如果中间位置的元素正好等于要查找的元素,就返回这个位置,否则的话,比较一下目标元素是比中间位置的元素大了还是小了,小了的话,说明在前半段中,否则相反。
总结:对于有序数组来说,二分查找是一种比较好的算法。
二分插入#
leetcode上有一道简单难度的题,找到目标值,返回索引,如果不存在,则返回插入位置,要求时间复杂度在O(logn)。很明显是让使用二分法来做。
int insert(vector<int>& nums, int begin, int end, int target)
{
if(begin == end) {
return begin;
}
int mid = (end - begin) / 2 + begin;
if(target == nums[mid]) {
return mid;
}
return target < nums[mid] ? insert(nums, begin, mid, target) :
insert(nums, mid + 1, end, target);
}
只需要把找不到的情况返回值从-1改成当前的下标即可。(end取闭区间还是开区间只会影响找不到时的判断条件,闭区间的话就是begin > end
,开区间的话就是begin == end
,STL中的做法都是取开区间,所以推荐和标准库保持一致,这样哪怕以后和库有交互也不至于头疼)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)