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

题目描述:

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
著作权归领扣网络所有。

栗子1:

输入: nums = [5,7,7,8,8,10], target = 8

输出: [3,4]

栗子2:

输入: nums = [5,7,7,8,8,10], target = 6

输出: [-1,-1]

思路:

看到题目之后,你最先想到的可能是for循环去遍历,可是本题对时间复杂度有一定的要求,所以此路不通。

时间复杂度必须是O(log n) ,再加上数据结构是升序排列的数组,那么很容易就联想到二分查找算法了。有没有“柳暗花明又一村”的感觉呢?

不过读完题之后,你会发现这和我们当初学习的二分查找还不太一样。当初二分查找返回的是目标值所在数组对应的下标,不存在则返回-1。所以呢,本题是二分查找的一个变形题目。如果你不清楚最基础的二分查找,可以先去看一下资料,之后再看这道题就会事半功倍。

这里呢,我认为你已经了解了二分查找算法,所以主要来讲一下寻找目标值的一些情况。数组的默认值最后说明哈,我们先从中间值左面的检索说起。中间值为mid,前一个元素就是mid-1,当mid-1=0的时候说明mid前面是有值的,属于需要检索的范围,如果mid-1<0,那么便超出了边界,可以终止检索。因为我们要找的是目标值第一次出现的位置,所以值需要等于目标值,在满足这两个条件的情况下进行检索。从中间值向右的检索也是一个道理。如果检索的过程中,发现了目标值,那么皆大欢喜。我们把它放到结果数组中即可,可是要是没找到怎么办呢?

如果中间值的左面和右面都没有目标值,那么我们返回什么呢?当然是{mid,mid}了,为什么?因为只有nums[mid]==target目标值的时候才会走进这个else语句,而且只有一个目标值。就好像{1,2,3},target=2;也有可能左面会有返回值,右面没有,就像{0,2,2,3,4},target=2;也有可能右面会有返回值,左面没有,就像{0,1,2,2,3},target=2。这样子是不是就可以想通了?

如果有什么错误或者问题,欢迎评论,我们一起探讨,一起进步。

代码:

public static int[] searchRange(int[] nums, int target) {
    int low = 0;
    int high = nums.length - 1;
    while (low <= high) {
        int mid = low + ((high - low) >> 1);
        if (nums[mid] < target) {
            low = mid + 1;
        } else if (nums[mid] > target) {
            high = mid - 1;
        } else {
            //注意
            int[] a = {mid, mid};
            //中间值向左检索(不包含中间值)
            int tmp = mid - 1;
            while (tmp >= 0 && nums[tmp] == target) {
                a[0] = tmp;
                tmp--;
            }
            //中间值向右检索(不包含中间值)
            tmp = mid + 1;
            while (tmp <= nums.length - 1 && nums[tmp] == target) {
                a[1] = tmp;
                tmp++;
            }
            //最终结果
            return a;
        }
    }
    return new int[]{-1, -1};
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章