题目描述:
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109
方法一:暴力求解
这五天以来做的第一道中等题目,其实很简单。但其实是使用的方法简单,所以性能也不不咋样。
思路:
1.逐个遍历,若第一次与目标值相等,则将此索引赋值给first与last这两个最终返回的结果,这里要记住,也要赋值给last,否则若数组中只有一位数且该数为目标值,那么last只是-1,而非该数的索引;
2.若非第一次与目标值相等(此时last!=-1),则将此索引赋值给last,
3.若该数与目标值不等,且last!=-1,说明该数组中已经曾经与目标值相等过,利用已排序的数组这一特性,直接跳出循环。
执行结果:通过
执行用时:1 ms, 在所有 Java 提交中击败了13.67%的用户
内存消耗:41.5 MB, 在所有 Java 提交中击败了70.44%的用户
通过测试用例:88 / 88
class Solution {
public int[] searchRange(int[] nums, int target) {
int first=-1;
int last=-1;
// int[] result=new int[]{first,last};//不能在此处先定义,否则result恒为[-1,-1]
for(int index=0;index<nums.length;index++){
if(nums[index]==target && first==-1){
first=index;
last=index; //若不加这句,那么在判断是类似[1] 1这类组合的时候,会返回[0,1]
}else if(nums[index]==target && first!=-1){
last=index;
}else if(nums[index]!=target && last!=-1){
break;
}
}
return new int[]{first,last};
}
}
方法二:二分查找法
思路:
1.二分查找法直接利用题给数组已经排好序的特点,设置了两个结点left与right,分别用于记录最终返回等于目标数的数组左右索引,设计了一个二分查找的方法binarySearch,这个方法用于找到第一个大于目标值的数的索引;
2.对于left,在binarySearch方法中找到第一个大于target-1的数的索引,这个索引就是第一个等于target的数的索引;
3.对于right,在binarySearch方法中找到第一个大于target的数的索引,这个索引 -1 就是最后一个等于target的数的索引;
4.最后判断,若nums[left]==target,说明在数组中能找到一个与target相等的值,返回最终索引;而left<=right这个判断用于表示所传数组非空,若数组为[ ],则会报出索引溢出的异常。
执行结果:通过
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:41.6 MB, 在所有 Java 提交中击败了44.37%的用户
通过测试用例:88 / 88
class Solution {
public int[] searchRange(int[] nums, int target) {
//left-->第一个比target-1大的元素的索引,正好就是target的第一个索引
int left=binarySearch(nums,target-1);
//right-->binarySearch(nums, target)返回的是第一个比target大的元素,减1是返回等于target的最后一个元素
int right=binarySearch(nums,target)-1;
if(left<=right && nums[left]==target){ //若无left<=righ,则容易发生left溢出
return new int[]{left,right};
}
return new int[]{-1,-1};
}
//寻找第一个大于target的数的下标
private int binarySearch(int[] nums,int target){//二分查找
int left=0, right=nums.length-1, index=nums.length;
while(left<=right){
int mid=(left+right)/2;
if(nums[mid]>target){//如果最中间的值>目标值
right=mid-1; //将右指针移到中间值左边(此时num[mid]可能==target)
index=mid; //记录第一个大于target的数的索引
}else{
left=mid+1;
}
}
return index;
}
}
平平无奇小白程序媛一枚,欢迎各位大佬交流指教,如有不正确的地方,欢迎留言改正,谢谢!!!