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