1 问题
1.1 英文描述
Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
1.2 中文描述
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
来源:力扣(LeetCode)
1.3 题意解析:
- 输入为一个按照升序排列的数组,数组中可能有相同元素
- 需要在时间复杂度O(log n)的情况下,找到给定的值的第一个和最后一个索引位置
- 如果没有找到,则返回第一个和最后一个索引为-1
2 解答
2.1 解题思路
- 先找到target在数组中最左边的索引
- 如果没有找到最左边的索引,那么说整个数组没有target,直接返回[-1, -1]
- 如果找到了最左边的索引,那么就再去找target在数组中最右边的索引
- 返回找到的两个边界的索引位置
2.2 代码实现:
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] indexes = {-1, -1};
int index = search(nums, target, true);
// 如果没找到target的最左边索引,就直接返回 [-1, -1]
if (index == nums.length || nums[index] != target) {
return indexes;
}
indexes[0] = index;
// 寻找最右边的索引,因为在寻找最右边索引时,left = mid + 1,所以需要把加的1减去才是正确的最右边索引
index = search(nums, target, false) - 1;
indexes[1] = index;
return indexes;
}
/**
* 找到target在数组中最左/右边的索引
*
* @param nums 数组
* @param target 要查找的值
* @param flag true表示查找最左边,false表示查找最右边
* @return 找到的索引位置,没找到返回 -1
*/
private int search(int[] nums, int target, boolean flag) {
int left = 0;
int right = nums.length;
int mid;
while (left < right) {
mid = left + (right - left) / 2;
// 当找最左边的索引时,只要 target 小于等于 nums[mid] 时,就继续找左边(包括mid)的数组
// 当找最右边的索引时,只要 target 大于等于 nums[mid] 时,就继续找右边的数组
if (target < nums[mid] || (flag && target == nums[mid])) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}