给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
1
2
3
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
1
2
3
提示:
- 你可以假设 nums 中的所有元素是不重复的。
- n 将在 [1, 10000]之间。
- nums 的每个元素都将在 [-9999, 9999]之间。
关键词:有序、无重复
方法一:闭区间 [left,right]
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0 ;
int right = nums.size()- 1;//[left,right]
int mid;
while(left <= right){
mid = left + (right-left)/2;
if(target<nums[mid]){
right = mid - 1;
}
else if(target>nums[mid]){
left = mid+1;
}
else if(target == nums[mid]){
return mid;
}
}
// 未找到目标值
return -1;
}
};
注意:①由于闭区间,定义right从num.size()-1开始
②while循环中,定义条件为left<=right,是因为取闭区间,left == right是有意义的
③target小于mid位置的值时,right转移到mid-1位置,因为闭区间取right,当前mid值必然不是target,排除此mid位置值
④为了防止left和right同时取int上限时导致的溢出,采用mid=left+(right-left)/2,此式等同于(left+right)/2
方法二:开区间 [left,right)
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while (left < right) {
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle;
}
else if (nums[middle] < target) {
left = middle + 1;
}
else { // nums[middle] == target
return middle;
}
}
// 未找到目标值
return -1;
}
};
注意:①由于开区间,定义right从num.size()开始
②while循环中,定义条件为left<right,是因为取开区间,left == right无意义
③left == right 时,在[left,right)是无效空间,所以用 >
③target小于mid位置的值时,right转移到mid位置,因为开区间取right,可以排除此mid位置值
拓展:
LEECODE 35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
- 输入: [1,3,5,6], 5
- 输出: 2
示例 2:
- 输入: [1,3,5,6], 2
- 输出: 1
示例 3:
- 输入: [1,3,5,6], 7
- 输出: 4
示例 4:
- 输入: [1,3,5,6], 0
- 输出: 0
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0 ;
int right = nums.size()- 1;//[left,right]
int mid;
while(left <= right){
mid = left + (right-left)/2;
if(target<nums[mid]){
right = mid - 1;
}
else if(target>nums[mid]){
left = mid+1;
}
else if(target == nums[mid]){
return mid;
}
}
return right+1;
}
};
本题可用暴力解法,但是题目中提到关键词--有序、无重复,我们可以尝试使用二分法。
其中我们需要处理四种情况:
- 目标值在数组所有元素之前
- 目标值等于数组中某一个元素
- 目标值插入数组中的位置
- 目标值在数组所有元素之后