1. 问题背景与核心挑战
在算法面试和日常编程中,处理排序数组的查找问题是最基础也最常考察的能力之一。LeetCode第34题"在排序数组中查找元素的第一个和最后一个位置"看似简单,却隐藏着二分查找算法最精妙的设计哲学。这道题在亚马逊、谷歌等大厂面试中的出现频率高达62%(根据2023年LeetCode企业题库统计)。
问题的正式描述是:给定一个按照非递减顺序排列的整数数组nums和一个目标值target,找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值,则返回[-1, -1]。要求算法时间复杂度必须为O(log n)。
关键提示:当面试官提出这个问题时,他们真正考察的是你对二分查找边界的理解深度,而不仅仅是能否写出一个能运行的解法。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 二分查找的边界陷阱
2.1 标准二分查找的局限性
大多数开发者第一次尝试这个问题时,会先写出标准二分查找,然后向左右两侧线性扩展搜索边界。例如:
java复制int standardBinarySearch(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
这种方法在找到目标后,需要向左向右遍历查找边界。最坏情况下(比如整个数组都是目标值),时间复杂度会退化到O(n),违反了题目要求。
2.2 边界条件的数学表达
要设计O(log n)的解法,需要重新定义搜索条件。我们需要两个独立的二分查找:
- 查找第一个等于target的位置(左边界):
- nums[mid] == target时,继续向左搜索(
