给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
思路
使用二分法的前提是数组为有序数组,同时需要数组中无重复的元素,有重复的元素,使用二分法查到的下标可能不是唯一的。
递归
public int search(int[] nums, int target) {
int l = 0;
int r = nums.length - 1;
return findTarget(l,r,nums,target);
}
public int findTarget(int left,int right,int[] nums,int target){
int a = (left+right)/2;
if (left <= right){
if(nums[a] == target){
return a;
}else if(nums[a] > target){
return findTarget(left,a-1,nums,target);
}else if(nums[a] < target){
return findTarget(a+1,right,nums,target);
}
}
return -1;
}
缺点:容易造成栈溢出
while循环(左闭右闭)
class Solution {
public int search(int[] nums, int target) {
int l = 0;
int r = nums.length - 1;//定义target在左闭右闭的区间里面,[l,r]
while (l <= r){ //当l == r时,区间[l,r]依然有效
int mid = (l+r)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] > target){
r = mid - 1; //target在左区间,在[l,mid - 1]
}else if(nums[mid] < target){
l = mid + 1; //target在右区间,在[mid + 1,r]
}
}
return -1;
}
}
while循环(左闭右开)
class Solution {
public int search(int[] nums, int target) {
int l = 0;
int r = nums.length - 1;//定义target在左闭右开的区间里面,[l,r)
while (l < r){ //当l == r时,区间[l,r)无效,所以这里是l < r
int mid = (l+r)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] > target){
r = mid - 1; //target在左区间,因为当前nums[mid]不等于 target,去左区间继续寻找,左区间是左闭右开的,,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
}else if(nums[mid] < target){
l = mid + 1; //target在右区间,在[mid + 1,r]
}
}
return -1;
}
}