【基础算法练习】二分模板

文章目录

二分模板题

704. 二分查找,这道题目是最经典的二分查找,使用于任何模板(如果你学的模板连这道题都套不上,那大概是模板有问题)

34. 在排序数组中查找元素的第一个和最后一个位置,一个合格的二分模板,需要能够应对这道题目的两种二分情况,我待会儿也会以这道题作为例题

二分的思想

我学算法也有一年了,二分相关的题目刷了也有 20 道以上,二分的模板也学了不下于 3 套,每一套都很有道理,但做他们选的题目是做对了,当遇到野生的二分题目的时候,时常失灵

我自己也在努力总结二分的本质,之前我一直认为二分的本质就是寻找单调性,但似乎并不是这样的,有单调性的题目确实一定可以用二分,但有些没有单调性的题目也可以用二分

其实二分的本质并不是单调性,当我们能将数据分成两个区间,一个区间不符合要求可以舍去,一个区间包含我们需要的答案,需要保留,这样的题目就能够使用二分

C++ 版本的二分

整数二分模板

模板一:用于左半区间不存在答案,而右半区间存在答案的情况,也就是在 left,mid mid + 1,right

cpp 复制代码
int l = 0, r = n - 1;
while (l < r) {
    int mid = l + r >> 1;
    if (check(mid)) r = mid;
    else l = mid + 1;
}

模板二:用于左半区间存在答案,而右半区间不存在答案的情况,也就是在 left,mid - 1 mid,right

cpp 复制代码
 int l = 0, r = n - 1;
 while (l < r) {
     int mid = l + r + 1 >> 1;
     if (check(mid)) l = mid;
     else r = mid - 1;
 }

模板记忆方法:有 - 1,那求 mid 的时候就需要 + 1

Golang 版本的二分

整数二分模板

模板一:用于左半区间不存在答案,而右半区间存在答案的情况,也就是在 left,mid mid + 1,right

go 复制代码
l, r := 0, len(nums)-1
for l < r {
    mid := l+(r-l)/2
    if check(mid) {
        r = mid
    } else {
        l = mid + 1
    }
}

模板二:用于左半区间存在答案,而右半区间不存在答案的情况,也就是在 left,mid - 1 mid,right

go 复制代码
l, r = 0, len(nums)-1
for l < r {
    mid := l+(r-l+1)/2
    if check(mid) {
        l = mid 
    } else {
        r = mid - 1
    }
}

例题:在排序数组中查找元素的第一个和最后一个位置

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置

题目描述

C++ 版本代码

cpp 复制代码
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if (nums.size() == 0) return {-1, -1};
        vector<int> ans;
        int l = 0, r = nums.size() - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (nums[mid] >= target) r = mid;
            else l = mid + 1;
        }
        
        if (nums[l] != target) return {-1, -1};
        ans.push_back(l);

        l = 0, r = nums.size() - 1;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (nums[mid] <= target) l = mid;
            else r = mid - 1;
        }
        ans.push_back(l);
        
        return ans;
    }
};

Golang 版本代码

go 复制代码
func searchRange(nums []int, target int) (ans []int) {
    if len(nums) == 0 {
        return []int{-1, -1}
    }
    l, r := 0, len(nums)-1
    for l < r {
        mid := l+(r-l)/2
        if nums[mid] >= target {
            r = mid
        } else {
            l = mid + 1
        }
    }
    if nums[l] != target {
        return []int{-1, -1}
    }
    ans = append(ans, l)
    l, r = 0, len(nums)-1
    for l < r {
        mid := l+(r-l+1)/2
        if nums[mid] <= target {
            l = mid 
        } else {
            r = mid - 1
        }
    }
    ans = append(ans, l)
    return ans
}
相关推荐
JieE2121 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
JieE2122 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack202 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树2 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2123 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2123 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术3 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦3 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户497863050733 天前
(一)小红的数组操作
算法·编程语言