LeetCode0035-搜索插入

二分查找

二分查找,这题的重点主要在于范围和条件的判断

题目

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

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

题解A

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

        while(left <= right){
            middle = left + (right - left)/2 ; 

            if(target == nums[middle] ){
                return middle ; 
            }else{
                if(target<nums[middle]){
                    right = middle - 1 ; 
                }else{
                    left = middle + 1 ;
                }
            }
        }

        return left ; 
    }
}

显然的二分,return的地方有两个:找到了目标值直接return,找不到就给个应该插入的下标
前者好理解,主要是后者
我们注意到循环的条件是left<=right,也就是我们在搜索完成前,left恒在rigth左侧或二者相等
当出循环的一瞬,left一定是在right右侧的,,而此时也意味着没找到target
临界前最后执行的是

    if(target<nums[middle]){
        right = middle - 1 ; 
    }else{
        left = middle + 1 ;
    }

意味着此时left所在的下标是大等于于middle,大等于right,那么我们就把target插入到这里

以上while循环中,若找到了target直接返回
原数组不包含target时,考虑while循环最后一次执行的总是 left=right=mid,
此时nums[mid] 左边的数全部小于target,nums[mid]右边的数全部大于target,
则此时我们要返回的插入位置分为两种情况:
①就是这个位置,即nums[mid]>target时,此时执行了right=mid-1,返回left正确
②是该位置的右边一个,即nums[mid]<target时,此时执行了left=mid+1,返回left也正确

这个算法在靠近数组边缘的时候不太好理解,下面的解法B会更好理解一点

题解B

public int searchInsert(int[] nums, int target) {
        //简单的二分查找
        if (nums == null || nums.length == 0) {
            return 0;
        }
        //小知识点: java数组的最大长度为int的最大值
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            if (target == nums[mid]) {
                return mid;
            } else if (target < nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        //此时left = right
        return target <= nums[left] ? left : left + 1;
    }

首先是第一个不同,循环的跳出
他们的更新条件是一样的,但这种做法在left=right的时候就会跳出循环
因此在return的时候额外做了一次判断target是否小于等于nums[left]
如果是,那刚刚好,我们就把目标放在left
如果不是,那意味着我们要把目标放在left的前一位

posted @ 2021-10-30 10:44  RetenQ  阅读(27)  评论(0编辑  收藏  举报