参考地址:https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/
目录
一、需求
A:给定一个排序数组(由小到大)和一个目标值,在数组中找到目标值,并返回其索引;
B:若目标值不存在于数组中,返回它将会被按顺序插入的位置;
C:假设数组中无重复元素;
二、暴力查找(复杂版)
-
思路分析
A:利用for循环对数组进行遍历,若找到目标值,则返回索引;
B:若数组中无目标值
a:若目标值小于数组第一个元素,则返回0;
b:若目标值大于数组最后一个元素,则返回数组长度;
c:若目标值在数组数据之间,则返回该插入位置的索引;
-
代码实现
public int searchInsert(int[] nums, int target) {
int i = 0, j = 0;
for (i = 0; i < nums.length; i++) {
if (nums[i] == target) {
return i;
}
}
// 数组中没有目标值
if (target < nums[0]) {
return 0;
} else if (target > nums[i - 1]) {
return i;
} else {
for (j = 0; j < i; j++) {
if (target > nums[j] && target < nums[j + 1]) {
return j + 1;
}
}
}
throw new IllegalArgumentException("No searchInsert solution");
}
-
复杂度分析
A:时间复杂度为O(n);
B:空间复杂度为O(1);
三、暴力查找(简化版)
-
思路分析
A:前面暴力破解法程序的可读性太差,需要进一步优化;
B:利用for循环得到每一个数组值与target进行比较
a:数组值大于等于target,那么直接返回该数组值对应的下标;
b:若没有大于target的,那么就返回数组长度;
-
代码实现
public int searchInsert(int[] nums, int target) {
int i;
for(i=0;i<nums.length;i++) {
if(nums[i]>=target) {
return i;
}
}
return i;
}
-
复杂度分析
A:时间复杂度为O(n);
B:空间复杂度为O(1);
四、二分查找(方式1)
-
思路分析
A:定义相关变量left和right以及mid用于二分查找,并进行初始化;
B:比较target与数组最后一个元素,若target大,则直接返回数组长度;
C:利用循环进行查找,若target找到了目标值,那就返回当前目标值的下标;
若target要大于目标值,则缩小查找范围使得left=mid+1;
若target要小于目标值,则缩小查找范围使得right=mid-1;
D:最后的返回值问题,如何证明返回left就是待插入位置?
这个目前还不明白,绕不过来;只能举例子,穷举法;
-
代码实现
public int searchInsert(int[] nums, int target) {
int left=0;
int right = nums.length-1;
if(target>nums[nums.length-1]) {
return nums.length;
}
while(left<=right) {
int mid = (left+right)/2;
if(target==nums[mid]) {
return mid;
} else if(target>nums[mid]) {
left=mid+1;
} else {
right=mid-1;
}
}
return left;
}
-
复杂度分析
A:时间复杂度为O(logn);
B:空间复杂度为O(1);
五、二分查找(方式2)
-
思路分析
A:上述算法在返回值上容易出问题,这里改进一下;
B:同样,定义left,right并初始化,判断目标值是否数组最后的元素,大于就返回数组长度;
C:循环的条件由left<=right改为left<right,这样退出循环,就不用担心返回谁了;
D:循环中定义mid并初始化;
E:当target要大于nums[mid]时,这时候left=mid+1,从而改变查找范围;
F:当target要小于等于nums[mid]时,这时候right=mid,使查找范围变为[left,mid];
G:最后返回left(right)均可;
-
代码实现
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
if(target > nums[right]) {
return nums.length;
}
while(left < right) {
int mid = left + (right - left)/2;
if(target > nums[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
-
复杂度分析
A:时间复杂度为O(logn);
B:空间复杂度为O(1);