力扣704. 二分查找
题目来源(力扣):
https://leetcode.cn/problems/binary-search/description/
题目描述:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
基本思路:
最基本的算法之一,考察对二分查找知识的掌握和基础编码能力。
难点主要是边界left、right处理,
参考《代码随想录》中,有2种写法,如下:
代码实现:
写法1 [left,right]
class Solution
{
public:
int search(vector<int> &nums, int target)
{ //[left,right]
int left = 0, right = nums.size() - 1;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if (nums[mid] > target)
{
right = mid - 1; // 这里是mid-1
}
else if (nums[mid] < target)
{
left = mid + 1; // 这里是mid+1
}
else
{
return mid;
}
}
return -1;
}
};
写法2 [left,right)
class Solution
{
public:
int search(vector<int> &nums, int target)
{ //[left,right)
int left = 0, right = nums.size();
int mid;
while (left < right)
{
mid = (left + right) / 2;
if (nums[mid] > target)
{
right = mid; // 这里是mid
}
else if (nums[mid] < target)
{
left = mid + 1; // 这里是mid+1
}
else
{
return mid;
}
}
return -1;
}
};
更多技巧:
当实际使用不好确认边界时,在更新前用left_old、right_old记录left、right,
从而确认left、right是否真正完成了更新,若未更新则直接退出循环
好处是不用在意左右边界,坏处是需要2个辅助空间,以及更多的判断
class Solution
{
public:
int search(vector<int> &nums, int target)
{ // 随意写法,不用在意左右边界
int left = 0, right = nums.size() - 1; //[left,right]
int left_old = left, right_old = right;
int mid;
while (left <= right)
{ // 这里一般直接写<=
left_old = left;
right_old = right;
mid = (left + right) / 2;
if (nums[mid] > target)
{
right = mid; // 不用写mid-1
}
else if (nums[mid] < target)
{
left = mid; // 不用写mid+1
}
else
{
return mid;
}
if (left_old == left && right_old == right)
{ // 临界条件
if (nums[left] == target)
return left;
else if (nums[right] == target)
return right;
else
break;
}
}
return -1;
}
};
时间复杂度
以上3种写法(或者说理论上二分查找的时间复杂度)为O(logn)
浙公网安备 33010602011771号