给定一个 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
理解区间的定义,在循环中始终坚持根据查找区间的定义来做边界处理。
区间的定义就是不变量,在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则。
int search(int* nums, int numsSize, int target){
int left=0,right=numsSize-1,middle;
while(left<=right){
middle=(right+left)/2;
if(nums[middle]>target){
right=middle-1;
}else if(nums[middle]<target){
left=middle+1;
}else return middle;
}
return -1;
}
比较标准的答案:
// (版本一) 左闭右闭区间 [left, right]
int search(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize-1;
int middle = 0;
//若left小于等于right,说明区间中元素不为0
while(left<=right) {
//更新查找下标middle的值
middle = (left+right)/2;
//此时target可能会在[left,middle-1]区间中
if(nums[middle] > target) {
right = middle-1;
}
//此时target可能会在[middle+1,right]区间中
else if(nums[middle] < target) {
left = middle+1;
}
//当前下标元素等于target值时,返回middle
else if(nums[middle] == target){
return middle;
}
}
//若未找到target元素,返回-1
return -1;
}
// (版本二) 左闭右开区间 [left, right)
int search(int* nums, int numsSize, int target){
int length = numsSize;
int left = 0;
int right = length; //定义target在左闭右开的区间里,即:[left, right)
int middle = 0;
while(left < right){ // left == right时,区间[left, right)属于空集,所以用 < 避免该情况
int middle = left + (right - left) / 2;
if(nums[middle] < target){
//target位于(middle , right) 中为保证集合区间的左闭右开性,可等价为[middle + 1,right)
left = middle + 1;
}else if(nums[middle] > target){
//target位于[left, middle)中
right = middle ;
}else{ // nums[middle] == target ,找到目标值target
return middle;
}
}
//未找到目标值,返回-1
return -1;
}