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

193 阅读4分钟

【题目】

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

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

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

示例 1:

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

示例 2:

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

示例 3:

输入: nums = [], target = 0
输出: [-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

【题目解析】

思路

二分查找法

为了满足时间复杂度的要求,本问题的解决方案是基于二分查找算法的变种。二分查找是一种在有序数组中查找特定元素的高效算法,其基本思想是通过比较数组中间元素与目标值的大小,逐步缩小搜索范围。在本问题中,我们需要进行两次二分查找:一次查找目标值的开始位置,另一次查找结束位置。

  1. 查找开始位置:修改二分查找算法,当找到等于目标值的元素时,继续在左侧查找,直到找到第一个等于目标值的元素。
  2. 查找结束位置:同样是修改二分查找算法,但是当找到等于目标值的元素时,继续在右侧查找,直到找到最后一个等于目标值的元素。

执行

image.png

【总结】

本问题的核心在于如何高效地在一个非递减排序数组中定位给定目标值的起始和终止位置。要求实现的算法时间复杂度为O(log n),这直接指向了二分查找法的使用,因为二分查找是解决排序数组查找问题的经典方法,其对数时间复杂度恰好符合题目要求。

适用问题类型

二分查找法及其变种适用于一系列与有序数据集相关的问题,包括但不限于:

  • 在排序数组中查找一个特定元素的位置。
  • 确定一个给定值的插入位置以保持数组的排序。
  • 查找有序数组中某个特定元素的出现次数。
  • 处理部分排序数组中的搜索问题,例如旋转排序数组的搜索。

此外,二分查找的思想也广泛应用于更复杂的算法和数据结构中,如平衡二叉搜索树的查询、最近点对问题的解决等。

解决算法:二分查找法的变体

本问题中使用了二分查找法的两个变体,分别用于查找目标值的开始位置和结束位置。核心思想是利用二分查找定位目标值,然后通过调整查找范围继续搜索以确定目标值的边界。这一过程涉及对二分查找的适当修改,即在找到目标值时不立即返回,而是继续探索以确定最终的边界位置。

算法特点

  • 时间复杂度:O(log n),其中n是数组长度。尽管进行了两次二分查找,但每次查找的时间复杂度仍然是对数级别的,因此满足题目要求。
  • 空间复杂度:O(1),算法在原地执行,仅使用了有限的额外空间。

算法优化和实践意义

在实践中,正确实现和优化二分查找算法需要注意细节,如处理查找范围的更新条件、避免整数溢出等。此外,理解二分查找的基本原理及其变种对于设计高效算法至关重要,可以帮助开发者解决一系列复杂度要求较高的搜索和排序问题。

总之,本问题不仅展示了二分查找在有序数组搜索问题中的应用,也强调了算法设计中对问题分析和解决策略选择的重要性。掌握这种方法,能够在面对各种有序数据集的搜索问题时,设计出既高效又简洁的解决方案。

题目链接

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