自己的第一想法
题目为寻找元素题型,因此时间复杂度优选二分查找法
-
使用普通的二分查找,区分不出左边界和右边界
-
瞄一眼卡哥的解题思路:分别找出左边界和右边界,自己尝试动手:
解决思路:
找左边界:
mid指针所指元素大于等于目标值时:right指针指向mid指针指向元素的前一个元素
mid指针所指元素小于目标值时:left指针指向mid指针指向元素的后一个元素找右边界:
mid指针所指元素小于等于目标值时:left指针指向mid指针指向元素的后一个元素
mid指针所指元素大于目标值时:right指针指向mid指针指向元素的前一个元素
但棘手的问题又发生了:如果元素在数组中不存在时返回-1,但又如何和找到左边界和右边界时的结果做区分呢
算了,还是借鉴卡哥的解题思路吧
看完随想录后的想法
解题思路和相关注解如下
找左边界,移动right指针:
mid指针所指元素大于等于目标值时:right指针指向mid指针指向元素的前一个元素,,并记录当前找到的左边界的位置
mid指针所指元素小于目标值时:left指针指向mid指针指向元素的后一个元素
找右边界,移动left指针:
mid指针所指元素小于等于目标值时:left指针指向mid指针指向元素的后一个元素,并记录当前找到的右边界的位置
mid指针所指元素大于目标值时:right指针指向mid指针指向元素的前一个元素
代码:
//根据条件不同结果不同,分为以下三种情况
情况1:target值小于数组第一个元素或大于最后一个元素
情况2:元素在数组中存在
情况3:target值大于数组第一个元素且小于最后一个元素,但在数组中不存在
public class SearchRange {
//根据条件不同结果不同,分为以下三种情况
public static int[] searchRange(int[] nums, int target) {
int leftRange = leftRange(nums,target);
int rightRange = rightRange(nums,target);
//情况1:target值小于数组第一个元素或大于最后一个元素
if(leftRange == -2 || rightRange == -2){
return new int[]{-1, -1};
}
//情况2:元素在数组中存在
if(rightRange-leftRange>1){
return new int[]{leftRange+1, rightRange-1};
}
//情况3:target值大于数组第一个元素且小于最后一个元素,但在数组中不存在
return new int[]{-1,-1};
}
找左边界:leftRange
为什么将左边界和右边界初始化为小于等于-2的任意一个数,而不是-1或者0或者正整数呢?
如果将左边界和右边界初始化为-1,元素中只有1个元素且这个元素就是我们要找的元素时,在找左边界的时候左边界的值leftRange就为-1,和初始化的值冲突,导致程序误认为是情况1,最终输出错误
例如以下情况:
nums ={1};
target = 1;
//找左边界
public static int leftRange(int[] nums,int target){
int leftRange = -2;
int left = 0;
int right = nums.length-1;
while(left<=right){
int mid = left+(right-left)/2;
if(nums[mid] >= target){
right = mid-1;
leftRange = right;//标记左边界的位置
}
else{
left = mid+1;
}
}
return leftRange;
}
找右边界:rightRange
//找右边界
public static int rightRange(int[] nums,int target){
int rightRange = -2;
int left = 0;
int right = nums.length-1;
while(left<=right){
int mid = left+(right-left)/2;
if(nums[mid] <= target){
left = mid+1;
rightRange = left;//标记右边界的位置
}
else{
right = mid-1;
}
}
return rightRange;
}
问题及总结
34题才开始做,属实有些蒙,但是跟着卡哥的讲解做下来,感觉还行,然后自己还是并想不出来这个解题思路,还是见得少,得多练