LeetCode 35.搜索插入位置

题目描述:

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • -104 <= target <= 104

解题思路:

此题需要解决两个问题:

(1)在数组中找到和目标元素相等的那个元素

(2)没有相等的元素,找到插入位置

而这两个问题实际上对应着四种情况:

(1)目标值target与数组中某个位置的值相等

(2)  目标值在数组范围内

(3) 目标值在数组范围外,小于所有元素

(4)目标值在数组范围外,大于所有元素

同时考虑到数组是顺序排列的,所以可以使用暴力解法和二分查找。

解题方法及解释:

方法1 暴力解法

就是target和数组中的每个元素挨个进行比较,然后找到目标值的位置

class Solution {
    public int searchInsert(int[] nums, int target) {
        for(int i=0; i<nums.length; i++){
            if(nums[i]>= target){
                return  i;
            }
        }
        return nums.length;
    }

}

为什么返回值是i :
如果有相等的元素则直接返回其所在的位置i, 如果没有但可以插入区间中的话,就是看target小于哪个值,小于的那个值的位置就是要插入的位置,因为target前面的数都是小于target的或者target直接就小于第一个值。

为什么返回值是nums.length:
如果元素比区间中所有的值都大的话就要查到数组的最后。

方法2 二分查找

二分查找第一种写法 [left,right] 左闭右闭,此方法有两个返回结果,下面进行解释

(1)返回值是mid和left

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length; 
		int left = 0;
		int right = n-1;

		while(left <= right){
			int mid = ((right -left)>> 1) + left;
			if(target == nums[mid]){
				return mid;
			}else if(target < nums[mid]){
				right = mid -1;
			}else{
				left = mid +1;
			}
		}

			return left;     /// 返回值是left
    }
}

(2)返回值是mid和right+1

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length; 
		int left = 0;
		int right = n-1;

		while(left <= right){
			int mid = ((right -left)>> 1) + left;
			if(target == nums[mid]){
				return mid;
			}else if(target < nums[mid]){
				right = mid -1;
			}else{
				left = mid +1;
			}
		}

			return right + 1;      ///返回值是right +1
    }
}

为什么left <= right:
因为二分查找一直需要去缩小范围直到找到所有的数字,缩小范围意味着边界变小,也就是左加右减,只有当左边界小于等于右边界时比较才有意义,也就是循环才能继续下去。而在这个过程中总会有右边界不断减直到小于左边界的时候,这个时候区间就无意义了,也就是再不能再缩小区间了,也就是循环结束了。

为什么返回值是mid: 
因为target始终要和mid进行比较,如果是情况1(等于)的话,就是我们想要的最理想的结果,找到这个值, target == nums[mid] 那就直接返回mid。

为什么返回值是right+1或者left:
还是target始终要和mid进行比较,如果不等于其中的元素,就需要缩小边界也就是左加右减,如果找到位置了必然会跳出循环,也就是右小于左,而此时left的位置就是要插入的位置(可以演算一下),而此时right +1 = left(包含了首位置[0],和尾位置[n])。

二分查找第二种写法 [left,right)左闭右开

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
		int left = 0;
		int right = n;

		while(left < right){
			int mid = ((right - left) >>1) + left;
			if(target < nums[mid]){
				right = mid;
			}else if( target > nums[mid]){
				left = mid +1;  
			}else{
				return mid;
			}
		}
		
		return right;

    }
}

为什么是left < right:
因为左比右开区间不能出现边界值相等的情况

为什么right = mid:
因为相比于上一解法的闭区间,开区间必须大一位才能包含数组中所有的整数,而mid 所在的位置刚好就是right的位置。
 

本文章参考内容

leetCode 35 题做题入口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值