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

文章目录

二分模板题

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
}
相关推荐
慢慢来_15 分钟前
【力扣热题100】[Java版] 刷题笔记-448. 找到所有数组中消失的数字
笔记·算法·leetcode
橘子遇见BUG2 小时前
算法日记 33 day 动态规划(打家劫舍,股票买卖)
算法·动态规划
格雷亚赛克斯2 小时前
黑马——c语言零基础p139-p145
c语言·数据结构·算法
南宫生2 小时前
力扣-位运算-3【算法学习day.43】
学习·算法·leetcode
Edward The Bunny2 小时前
[算法] 前缀函数与KMP算法
算法
码农多耕地呗2 小时前
区间选点:贪心——acwing
算法
醉酒柴柴3 小时前
【代码pycharm】动手学深度学习v2-08 线性回归 + 基础优化算法
深度学习·算法·pycharm
财富探秘者3 小时前
贵州茅台[600519]行情数据接口
大数据·c语言·python·算法·金融·restful
至善迎风3 小时前
施密特正交化与单位化的情形
线性代数·算法·决策树·机器学习
HABuo4 小时前
【数据结构与算法】合并链表、链表分割、链表回文结构
c语言·开发语言·数据结构·c++·学习·算法·链表