题目:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 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(int[] nums, int target) {
int length = nums.length;
int left = 0;
int right = length-1;
int mid;
while(left <= right){
mid = (left + right)/2;
if (nums[mid] > target){
right = mid-1;
} else if (nums[mid] < target) {
left = mid+1;
} else {
return mid;
}
}
return right+1;
}
}
题解:
这道题,在一个有序数组中插入目标值,有四种情况
- 目标值在数组所有元素之前
- 目标值对于数组中其中一个元素
- 目标值插入其中一个位置
- 目标值在所有位置之后
从题目可知,这是一个有序数组,且无重复元素,首先想到的是二分法
二分法要注意的就是二分的边界,在循环过程中是保持不变的,这就是循环不变量
二分的区间是要[left,right],还是要用[left,right),这取决于while条件是while( left<=right)还是 while(left<right)
- 在while( left<=right)中当 left=right 时,区间[left,right]依然有效
- 在while( left<right)中当 left=right 时,区间[left,right)无效
使用左闭右闭的区间二分时,要注意最后返回的是 right+1
这是因为二分到最后时,区间会缩小到相邻的两个元素【n,n+1】,而mid =(n+(n+1))/2总是会等于n,即先从左边下标n的元素与目标值判断,若目标值小于num[mid],则目标值插入下标为mid,此时right=mid-1,故返回right+1
二分法的时间复杂度为log2 N:
折数组长度为N,第一次二分,长度为N/2,第二次为N/4,第k次为N/2^k
由于二分的次数为执行的次数,即时间复杂度为k,又二分到最后数组长度约等于1,N/2^k=1,可得k=log2 N,即时间复杂度为(logN)