题目来源:搜索插入位置——每日一练第3天(Java语言)
同时也是:LeetCode 35. 搜索插入位置
题目详情
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。
示例 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
解题思路
题目比较简单,如果采用暴力解法,时间复杂度为O(n),其实也不算慢,但是用二分查找的话肯定更好一些,而且在LeetCode上明确要求时间复杂度为O(logn),那就用二分查找呗。
方法一 暴力解法
就从左往右遍历数组
- 如果目标元素
target
比第i
个元素小且比第i-1
个元素大,那么就返回i
- 如果遍历数组时发现等
i
个元素和target相等,那么就返回i
- 当然,以上条件可以合并(见代码)
方法二:二分查找
先找有序数组中中间的那个元素,让target
与其比较:
- 如果
traget
比中间元素小,则在中间元素的右边查找 - 如果
traget
比中间元素大,则在中间元素的右边查找 - 如果
traget
比中间元素相同,则返回中间元素的下标 - 就这么一直缩小范围比较下去,直到比较完
代码实现
方法一:暴力解法
public class SearchInsertPosition {
public static void main(String[] args) {
Solution solution = new SearchInsertPosition().new Solution();
// to test
int[] nums = {1,3,5,6};
int target = 1;
System.out.println(solution.searchInsert(nums,target));
}
class Solution {
public int searchInsert(int[] nums, int target) {
if(target < nums[0]) { // 特殊情况:目标值比有序数组的第一个元素还小
return 0;
}
if(target > nums[nums.length-1]) { // 特殊情况:目标值比有序数组的最后一个元素还大
return nums.length;
}
int target_index = 0;
for(int i = 1 ; i < nums.length; i++) {
if(target <= nums[i] && target > nums[i-1]) {
target_index = i;
}
}
return target_index;
}
}
}
方法二:二分查找
public class SearchInsertPosition {
public static void main(String[] args) {
Solution solution = new SearchInsertPosition().new Solution();
// to test
int[] nums = {1,3,5,6};
int target = 1;
System.out.println(solution.searchInsert(nums,target));
}
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
if(target < nums[left]) { // 特殊情况:目标值比有序数组的第一个元素还小
return 0;
}
if(target > nums[right]) { // 特殊情况:目标值比有序数组的最后一个元素还大
return nums.length;
}
while(left <= right) {
int mid = (left + right) / 2;
if(nums[mid] < target) { // 查找区域:[mid+1,right]
left = mid + 1;
} else if(nums[mid] > target) { // 查找区域:[left,mid-1]
right = mid - 1;
} else {
return mid;
}
}
return left;
}
}
}