34. 在排序数组中查找元素的第一个和最后一个位置

题目:

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

你的算法时间复杂度必须是 O(log n) 级别。

如果数组中不存在目标值,返回 [-1, -1]。

示例:

image.png

思路:

二分查找(二分查找很简单,细节很重要)
通过查找一个数的左边界,可以找到目标数的左边界;
然后查找比目标数大一的数(target = 8 ----> 找8+1)的左边界,这个数的左边界 -1 就是目标数的右边界。

重点:
怎么通过二分查找,找到目标数的左边界?

参考:作者:labuladong
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/er-fen-cha-zhao-suan-fa-xi-jie-xiang-jie-by-labula/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

代码:

int left_bound(int[] nums, int target) {
    if (nums.length == 0) return -1;
    int left = 0;
    int right = nums.length; // 注意
    
    while (left < right) { // 注意
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
            right = mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid; // 注意
        }
    }
    return left;
}

代码:

class Solution {
    public int[] searchRange(int[] nums, int target) {
       //查找目标数的左边界
       int first = binarySearch(nums, target);
       //查找目标数的右边界(即目标数+1的数的左边界-1)
       int last = binarySearch(nums, target + 1) - 1;
       //如果左边界等于数组长度,即目标数比数组所有数都大
       //或者左边界的数不等于目标数,目标数比所有数都小
       if (first == nums.length || nums[first] != target) {
           //即,找不到目标数,就返回-1
           return new int[]{-1, -1};
       } else {
           //否则,返回左右边界。
           return new int[]{first, last};
       }
    } 

    //查找左边界的二分查找
    public int binarySearch(int[] arr, int target) {
        int l = 0;
        int h = arr.length;
        //注意条件是l<h
        while (l < h) {
            int mid = l + ((h - l) >>> 1);
            if (target <= arr[mid]) {
                h = mid;
            } else if (target > arr[mid]) {
                l = mid + 1;
            }
        }
        return l;
    }
}

时间复杂度:O(logn),空间复杂度:O(1)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容