题目:
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
示例 1:
输入:nums
= [-1,0,3,5,9,12],target
= 9 输出: 4 解释: 9 出现在nums
中并且下标为 4
示例 2:
输入:nums
= [-1,0,3,5,9,12],target
= 2 输出: -1 解释: 2 不存在nums
中因此返回 -1
提示:
- 你可以假设
nums
中的所有元素是不重复的。 n
将在[1, 10000]
之间。nums
的每个元素都将在[-9999, 9999]
之间。
思路:
与题目名称一样,由于是有序数组,查找可以使用二分查找(Binary Search)。时间复杂度为O()
二分查找过程:
找出数组中间位置的值,将数组分成两半,由于是有序数组(题目中是升序),因此左半部分一定比中间值小,右半部分一定比中间值大。
将中间值与目标值做比较,如果目标值比中间值大,则在右半侧数组中继续查找。如果目标值比中间值小,则在左半侧数组中继续查找。如果中间值与目标值相等,则返回中间值下标。
需要注意数组下标的变化在代码中的设计(需要三个指针,min,mid,max来存储中间值以及查找范围的数组下标)。
重复上述操作,直到查找范围缩小到1(min>=max)。
未找到目标值返回-1。
解题过程:
首先获得数组长度
int length = nums.size();
声明变量设置查找边界
int min = 0, max = length - 1;
获取边界范围内的中间值下标
int mid = min + (max - min)/2;
为什么不用(max+min)/2呢?如果数组较长,C++中int类型容易溢出报错。python整数支持任意精度,所以两种均可。但为了代码在不同语言中的可迁移性,选择min + (max - min)/2。
判断target与nums[mid]的关系
如果目标值小于中间值,移动右边界(中间值已经被比较过,所以max = mid - 1)。
if(target < nums[mid]){
max = mid - 1;
}
如果目标值大于中间值,移动左边界(中间值已经被比较过,所以min = mid + 1)。
else if(target > nums[mid]){
min = mid + 1;
}
如果中间值与目标值相等,则返回下标mid;
else{
return mid;
}
设置循环体,如果左边界与右边界重合(此时mid = (min+max)/2赋值后mid = max = min)或交叉,说明查找已到尽头。
while(min >= max){
}
循环结束后
return -1;
题解:
class Solution {
public:
int search(vector<int>& nums, int target) {
int length = nums.size();
int min = 0, max = length - 1;
while(min<=max){
int mid = min + (max - min)/2;
if(target < nums[mid]){
max = mid - 1;
}else if (target > nums[mid]){
min = mid + 1;
}else{
return mid;
}
}
return -1;
}
};