LeetCode第34题:在排序数组中找到元素的第一个和最后一个位置
2023-11-11 21:03:20
揭秘LeetCode第34题:在排序数组中查找元素的第一个和最后一个位置
简介
欢迎来到算法探索之旅!LeetCode第34题,中等难度,是一个经典的数据结构与算法问题,旨在考察你的逻辑思维能力和编程技巧。在这篇博客中,我们将深入探讨这道题目的最佳解法,分析其复杂度,并提供全面的代码示例。
题目剖析
给定一个按照升序排列的数组nums
和一个目标值target
,我们的任务是找到target
在数组中出现的第一个和最后一个位置。如果target
不存在于数组中,则返回[-1,-1]
。
解题思路
针对这道题,主要有两种常用的解法:
二分查找
二分查找是一种高效的算法,利用数组有序的特性,通过不断缩小搜索范围来查找元素。具体步骤如下:
- 初始化两个指针
left
和right
,分别指向数组的第一个和最后一个元素。 - 计算数组的中点
mid
,并与target
进行比较。 - 如果
nums[mid]
小于target
,则target
在数组的右半部分,将left
指针移动到mid
的下一位。 - 如果
nums[mid]
大于target
,则target
在数组的左半部分,将right
指针移动到mid
的前一位。 - 重复步骤2-4,直到找到
target
或left
和right
指针交叉。
遍历查找
遍历查找是一种更直观的解法,它从数组的第一个元素开始,逐个元素与target
进行比较,直到找到target
或遍历完整个数组。
代码实现
Python
def search_range(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# 二分查找
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
# 找到目标值,然后向左和向右扩展,找到第一个和最后一个位置
start, end = mid, mid
while start >= 0 and nums[start] == target:
start -= 1
while end < len(nums) and nums[end] == target:
end += 1
return [start + 1, end - 1]
# 目标值不存在于数组中
return [-1, -1]
Java
public int[] searchRange(int[] nums, int target) {
int[] result = new int[]{-1, -1};
int left = 0;
int right = nums.length - 1;
// 二分查找目标值
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
// 找到目标值,向左和向右扩展
int start = mid;
int end = mid;
while (start >= 0 && nums[start] == target) {
start--;
}
while (end < nums.length && nums[end] == target) {
end++;
}
result[0] = start + 1;
result[1] = end - 1;
break;
}
}
return result;
}
复杂度分析
二分查找
- 平均时间复杂度: O(log n),其中n是数组的长度。
- 最坏时间复杂度: O(n),当数组中不存在目标值时。
遍历查找
- 时间复杂度: O(n),因为需要遍历整个数组。
注意: 二分查找的平均时间复杂度远低于遍历查找,但在最坏情况下,它们的时间复杂度相同。
总结
LeetCode第34题是一个经典的算法问题,考察了我们的逻辑思维能力和编程技巧。通过二分查找或遍历查找,我们可以有效地找到目标值在排序数组中的第一个和最后一个位置。二分查找在平均情况下效率更高,但遍历查找更容易理解和实现。选择哪种方法取决于具体情况和性能需求。
常见问题解答
-
为什么二分查找的平均时间复杂度是O(log n)?
因为每一步二分查找将搜索范围缩小一半,导致搜索空间呈指数级下降。 -
二分查找为什么在最坏情况下需要O(n)的时间复杂度?
当目标值不存在于数组中时,二分查找需要遍历整个数组才能得出结论。 -
遍历查找比二分查找简单,为什么不总是使用遍历查找?
当数组规模较大时,二分查找的平均时间复杂度远低于遍历查找。 -
我可以同时使用二分查找和遍历查找吗?
可以,如果优先考虑性能,可以使用二分查找来快速找到目标值的大致位置,然后再使用遍历查找来精确找到第一个和最后一个位置。 -
LeetCode第34题还有其他解法吗?
除了二分查找和遍历查找之外,还可以使用哈希表来存储元素的位置,实现常数时间查找。但是,这需要额外的空间复杂度。