文章目录
- 前言
- 一、题目
- 1、原题链接
- 2、题目描述
- 二、解题报告
- 1、思路分析
- 2、时间复杂度
- 3、代码详解
- 三、知识风暴
前言
本专栏文章为《代码随想录》书籍的刷题题解以及读书笔记,如有侵权,立即删除。
一、题目
1、原题链接
704. 二分查找
2、题目描述
二、解题报告
1、思路分析
二分查找有一般有两种写法,主要思想是利用搜索区间的定义来确定代码条件:
[left,right]
(左闭右闭)
如果将区间定义为左闭右闭,则意味着left
和right
的值都可以取到,而且left
和right
的值可以相等。所以:- 初始
left=0
、right=nums.size()-1
。 - 循环条件需要设置为
left<=right
- 当
nums[mid]>target
时,更新right=mid-1
。(因为根据区间定义,此时如果使right=mid
,区间可以取到mid
,而已知mid
不满足条件,故应将区间缩小为[left,mid-1]
) - 当
nums[mid]<target
时,更新为left=mid+1
。(因为根据区间定义,此时如果使left=mid
,区间可以取到mid
,而已知mid
不满足条件,故应将区间缩小为[mid+1,right]
) - 当
nums[mid]==target
时,返回mid
。 - 否则,返回
-1
。
- 初始
[left,right)
(左闭右开)
如果将区间定义为左闭右开,则意味着left
的值可以取到,而right
的值取不到,而且left
和right
的值不可以相等。所以:- 初始
left=0
、right=nums.size()
。 - 循环条件需要设置为
left<right
- 当
nums[mid]>target
时,更新right=mid
。(因为根据区间定义,此时如果使right=mid-1
,区间取不到mid-1
,会使搜索区间丢失mid-1
,故应将区间缩小为[left,mid)
) - 当
nums[mid]<target
时,更新left=mid+1
。(因为根据区间定义,此时如果使left=mid
,区间可以取到mid
,而已知mid
不满足条件,故应将区间缩小为[mid+1,right)
) - 当
nums[mid]==target
时,返回mid
。 - 否则,返回
-1
。
- 初始
2、时间复杂度
二分查找时间复杂度为O (log n)
3、代码详解
左闭右闭区间定义代码
class Solution {
public:int search(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left <= right) {//防止溢出可以改为://int mid = left + ((right - left) / 2);//或//int mid = left + ((right - left) >> 1);int mid = (left + right) / 2;if (nums[mid] > target) right = mid - 1;else if (nums[mid] < target) left = mid + 1;else return mid;}return -1;}
};
左闭右开区间定义代码
class Solution {
public:int search(vector<int>& nums, int target) {int left = 0, right = nums.size();while (left < right) {//防止溢出可以改为://int mid = left + ((right - left) / 2);//或//int mid = left + ((right - left) >> 1);int mid = (left + right) / 2;if (nums[mid] > target) right = mid;else if (nums[mid] < target) left = mid + 1;else return mid;}return -1;}
};
三、知识风暴
- 注意
mid
是下标不是值,与target
比较时是用nums[mid]
。 - 防止溢出可以将
int mid = (left + right) / 2;
改为int mid = left + ((right - left) / 2);
或int mid = left + ((right - left) >> 1);
。 - 数组理论基础
- 数组下标都是从0开始的
- 数组在内存空间的地址是连续的
- 数组中的元素只能覆盖,不能删除。