题目描述
给定一个按照升序排列的整数数组 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]
分析
先创建要返回的 result 数组,长度为2,初始值为 -1
方法一: 可以直接遍历整个 nums 数组,如果数组中出现 target 值,将这个首次出现的位置记录到 result 数组,继续遍历记录下一个位置,注意,如果出现 target 值,result[0] 的赋值操作只执行一次,需要一个 flag 值记录是否进行过赋值操作,或者判断 result[0] 的值是否为 -1,不是 -1 则进行赋值
方法二: 二分查找,找 target 值在数组中的位置,不存在直接返回值为 -1 的初始 result 数组,如果存在,再在这个位置两边找到它的范围
Code(Java)
第一种:暴力
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = new int[2];
result[0] = result[1] = -1;
int flag = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == target) {
if(flag == 0) { //或 if(result[0] != -1)
result[0] = i;
flag = 1;
}
result[1] = i;
}
}
return result;
}
}
第二种:二分法
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = new int[2];
result[0] = result[1] = -1;
int left = 0, right = nums.length-1;
int t = -1; //用于记录是否找到
while(left <= right) { //二分
int mid = (left + right) / 2;
if(nums[mid] == target) { //数组中存在 target 值,则记录它的位置并跳出循环
t = mid;
break;
}
if(nums[mid] < target) {
left = mid+1;
}else {
right = mid-1;
}
}
if(t == -1) { //t 为 -1,代表数组中不存在 target 值,直接返回值为 -1 的初始数组
return result;
}
//数组中存在 target 值
for(int i = t; i > -1; i--) { //在 t 左边找 target 第一次出现位置
if(nums[i] == target) {
result[0] = i; //将第一次出现的位置保存在 result 数组中
}
}
for(int i = t; i < nums.length; i++) { //在 t 右边找 target 最后一次出现位置
if(nums[i] == target) {
result[1] = i; //将最后一次出现的位置保存在 result 数组中
}
}
return result;
}
}