标准答案,O(logN),明天学一下,今天困了
java
class Solution {
public int[] searchRange(int[] nums, int target) {
// 1. 先找左边界
int leftBorder = findBound(nums, target, true);
// 如果左边界都没找到,说明数组里根本没有这个数,直接返回 [-1, -1]
if (leftBorder == -1) {
return new int[]{-1, -1};
}
// 2. 再找右边界
int rightBorder = findBound(nums, target, false);
return new int[]{leftBorder, rightBorder};
}
/**
* 核心辅助函数:二分查找
* @param isFirst 如果是 true,表示查找第一个位置(左边界);false 表示查找最后一个位置(右边界)
*/
private int findBound(int[] nums, int target, boolean isFirst) {
int left = 0;
int right = nums.length - 1;
int candidate = -1; // 用来暂存找到的 target 下标
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 {
// 核心逻辑:当 nums[mid] == target 时
candidate = mid; // 1. 先记录当前位置(因为可能是答案)
// 2. 决定接下来往哪边缩
if (isFirst) {
right = mid - 1; // 如果找左边界,就缩小右边界,继续往左边搜
} else {
left = mid + 1; // 如果找右边界,就缩小左边界,继续往右边搜
}
}
}
return candidate;
}
}
下面是我写的O(n)的
java
class Solution {
public int[] searchRange(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int foundIndex = -1; // 用来记录找到的那个位置
// 1. 标准二分查找,只要找到一个就行
while (left <= right) {
int mid = left + (right - left) / 2;
if (target < nums[mid]) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
// 找到目标了!记录位置,直接跳出循环
foundIndex = mid;
break;
}
}
// 2. 如果没找到,直接返回 -1, -1
if (foundIndex == -1) {
return new int[] {-1, -1};
}
// 3. 以 foundIndex 为中心,向两边扩散 (这就是你卡住的地方)
int start = foundIndex;
int end = foundIndex;
// 向左找边界
while (start > 0 && nums[start - 1] == target) {
start--;
}
// 向右找边界
while (end < nums.length - 1 && nums[end + 1] == target) {
end++;
}
return new int[] {start, end};
}
}