题目描述:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例:
示例 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
二分搜索算法:
方法一:递归版
思路分析:
给一个有序数组,一个目标值,若找到就返回其该目标值的索引。若找不到就返回其应该按顺序插入的位置。
与二分搜索不同的是:
二分搜索如果找不到目标值会返回 -1 来提示我们,而在这里则是要返回该值应插入的位置,所以我们只用改动一种情况,即找不到目标值的情况。所以只用对(left > right)这种情况进行修改即可。
如何修改:
1)如果目标值小于数组的第一个元素,说明它最小,则返回0即可
2)如果目标值大于数组的最后一个元素,说明它最大,则返回数组长度即可(arr.lenth - 1 +1)
3)如果目标值刚好在数组的中间,那么根据推算,此时目标值target 应该大于right,小于left,正好夹在中间,所以返回 right -1或 left +1即可
代码:
class Solution {
public int searchInsert(int[] nums, int target) {
return binarySearch(nums,0,nums.length-1,target);
}
public int binarySearch(int[] nums,int left,int right,int target){
if(left > right){
if(target < nums[0]){
return 0;
}else if(target > nums[nums.length-1]){
return nums.length;
} else {
return right + 1;
}
}
int mid = (left + right) / 2;
int midVal = nums[mid];
if(target > midVal){//要找的值大于nums[mid],说明要找的数在mid右边
return binarySearch(nums,mid+1,right,target);
}else if(target < midVal){//要找的值小于nums[mid],说明要找的数在mid左边
return binarySearch(nums,left,mid-1,target);
}else {//target == midVal
return mid;
}
}
}
方法二:非递归版
实现原理同上:
代码:
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
while(left <= right){
int mid = (left + right) / 2;
if(target > nums[mid]){
left = mid + 1;
}else if(target < nums[mid]){
right = mid - 1;
}else{
return mid;
}
}
if(target < nums[0]){
return 0;
}else if(target > nums[nums.length-1]){
return nums.length;
}else{
return right + 1;
}
}
}