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),
然后再具体去写,
这样就不会出现因为范围问题而不知道怎么去写,无从下手。

猜你喜欢

转载自blog.csdn.net/Bellwen/article/details/128054493