题目链接:二分查找
关键点:
【1】数组为有序数组;
【2】数组中无重复元素(有重复元素,则找到的下标不唯一)。
思路:二分法对于区间的判定非常重要,一般有[Left,Right]
左闭右闭和[Left,Right)
左闭右开两种区间。因此区间不同,写法也不同。
1)左闭右闭区间写法
#include <iostream>
#include <vector>
class Solution
{
public:
int search(std::vector<int>& nums, int target)
{
int left = 0; // 左边界
int right = nums.size() - 1; // 右边界,right作为下标使用,所以需要-1
while (left <= right) // nums[right]可以取到,left <= right有意义
{
int middle = left + ((right - left) / 2); // 等同于(left + right)/2,但可避免left + right溢出的可能
if (nums[middle] < target) // 说明target在[middle+1,right]区间
{
left = middle + 1; // 更新左边界left
}
else if(nums[middle] > target) // 说明target在[left,middle-1]区间
{
right = middle - 1;
}
else // 说明nums[middle] == target
{
return middle;
}
}
return -1; // 未找到目标
}
};
int main()
{
std::vector<int> vec = { 1,2,3,4,5,6,7,8,9 };
Solution s;
int ret = s.search(vec, 6);
std::cout << ret << std::endl;
return 0;
}
2)左闭右开区间写法
#include <iostream>
#include <vector>
class Solution
{
public:
int search(std::vector<int>& nums, int target)
{
int left = 0; // 左边界
int right = nums.size(); // 右边界,因为是开区间,所以不用-1
while (left < right) // nums[right]不可能取到,因此left < right
{
int middle = left + ((right - left) >> 1); // 右移一位相当于除2
if (nums[middle] < target) // 说明target在[middle+1,right)区间
{
left = middle + 1; // 更新左边界left
}
else if(nums[middle] > target) // 说明target在[left,middle)区间
{
right = middle;
}
else // 说明nums[middle] == target
{
return middle;
}
}
return -1; // 未找到目标
}
};
int main()
{
std::vector<int> vec = { 1,2,3,4,5,6,7,8,9 };
Solution s;
int ret = s.search(vec, 6);
std::cout << ret << std::endl;
return 0;
}