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

144 阅读2分钟

题目表述

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

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

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

来源:力扣(LeetCode)
链接:leetcode.cn/problems/fi…

难点分析

  • 按照题目要求,可以分为如下四种情况处理:

    1. 情况0:数组没有元素:
      • if(nums.size() == 0) return {-1, -1};
    2. 情况一:target数值在非递减数组两端之外:return {-1, -1}
      • 解法:直接判断target是否小于排序数组最小元素,或大于排序数组最大元素。
        • if(target < nums[0] || target > nums[nums.size() - 1]) return {-1, -1};
    3. 情况二:target数值在数组两端内,但target值不在数组中:return {-1, -1}
    4. 情况三:target数值在数组中可以找到:return {left, right}
  • 对于情况二和三,我们采用二分法。

    • 根据普通的二分查找,我们可以轻而易举找到该元素在数组中的下标,接下来,继续二分查找,寻找左右边界。
    • 寻找左边界:当找到与target相等元素时可知,最左元素的上一个位置一定在target左边,于是继续向左寻找right = mid - 1;
    • 寻找右边界:当找到与target相等元素时可知,最右元素的下一个位置一定在target右边,于是继续向右寻找left = mid + 1;
    • 为什么是最左右元素的下一个位置?
      • 这里采用左闭右闭区间,当利用原while循环继续寻找时,执行right = mid - 1;,left = mid + 1;,因此是下一位置。
    • 第二种情况:由于我们计算出的左右边界是左右端的下一位置,因此,若情况二出现,二分查找中应该找到同一位置,左右边界应该重合,有:
      • if(left == right) return {-1, -1};
    • 第三种情况,返回计算的左右边界即可。