C++:二分法基础模板-Leetcode-704题二分查找

C++:二分法基础模板-Leetcode-704题二分查找

二分法的最为基础的模板思路,以及一些易错点的记录



二分法基础

使用二分法前提:数组元素有序排列,且没有重复元素!!!!
二分法一般的两种写法:
1.先确定区间类型,是左闭右闭区间[],还是左闭右开区间[)
2.通过区间类型判定循环的条件类型:
[]区间时,while(left<=right);
[)区间时,while(left<right);
3.再去写二分法的具体内容
二分法时间复杂度O(log2n),比暴力法效率高


题目

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

思路分析

/*
代码随想录-数组-二分法
使用二分法前提:数组元素有序排列,且没有重复元素!!!!
二分法一般的两种写法:
1.先确定区间类型,是左闭右闭区间[],还是左闭右开区间[)
2.通过区间类型判定循环的条件类型:
[]区间时,while(left<=right);
[)区间时,while(left<right);
3.再去写二分法的具体内容

两种方法,建议熟记第一种[]。
注意事项:
1.求middle时,middle = left+(right-left)/2,等价于middle = (right-left)/2,加上left是防止溢出
2.二分法使用前提是,数组元素有序排列,且没有重复元素
3.二分法空间复杂度是常量O(1),时间复杂度O(log(n))

*/

/*
------------此程序默认vector为升序数组,无重复元素
*/

//leetcode 704题
#include "iostream"
#include "vector"
using namespace std;

//方法1,[]区间
class Solution1
{
private:
public:
    int search(vector<int> &nums, int target)
    {
        int left = 0;
        int right = nums.size() - 1;
        int middle;
        while (left <= right)
        {
            middle = left + (right - left) / 2;
            if (nums[middle] > target) //即nums[middle]在target的右边,对于升序数组来说
            {
                right = middle - 1; //注意区分
            }
            else if (nums[middle] < target) //即nums[middle]在target的左边
            {
                left = middle + 1;
            }
            else
            {
                return middle; //找到nums[middle] == target,返回vector下标
            }
        }
        return -1;
    }
};

//方法2,[)区间
class Solution2
{
private:
public:
    int search(vector<int> &nums, int target)
    {
        int left = 0;
        int right = nums.size();
        int middle;
        while (left < right) //因为右边是开区间
        {
            middle = left + (right - left) / 2;
            if (nums[middle] > target)
            {
                right = middle; //因为右边是开区间,如果此处也right=middle-1,但right是开区间,下一次循环则不会去判断middle-1这个元素,则将出现丢失情况
            }
            else if (nums[middle] < target)
            {
                left = middle + 1; //因为左边是闭区间
            }
            else
            {
                return middle;
            }
        }
        return -1;
    }
};

int main(int argc, const char **argv)
{
    vector<int> nums;
    for (int i = 0; i < 10; i++)
    {
        nums.push_back(i + 10);
    }

    Solution1 s1;
    cout << s1.search(nums, 10) << endl;

    Solution2 s2;
    cout << s2.search(nums, 10) << endl;
    return 0;
}

总结

重点掌握第一种闭区间的写法,好理解。
先确定left=0、right=nums.size()-1,
然后确定while(left<=right),
然后再具体去写,
这样就不会出现因为范围问题而不知道怎么去写,无从下手。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值