leecode34在排序数组中查找元素的第一个和最后一个位置-手写详解
源代码的一些注解
我这个的思路是先找出这个target,找到了之后在便利这个target周围的变量,相当于是做了一个二分搜索算法之后,当这个range范围比较小的时候我这种方法的时间复杂度比较低,但是当这个range范围比较大的时候我的时间复杂度应该是比两个二分搜索算法所需时间多的.
我在代码随想录网站上看的这个题的题解是利用了两个二分搜索法进行计算,第一个二分搜索确定左边界,第二个二分搜索算法确定右边界,然后最后确定这个总边界.相对而言时间复杂度会更高一点.我自己做题的时候并没有想到这个算法.
源代码
package 数组;
import java.util.Scanner;
public class 在排序数组中查找元素的第一个和最后一个位置 {
public static void main(String[] args) {
int n;
Scanner input = new Scanner(System.in);
System.out.println("请输入数组的长度");
n=input.nextInt();
int[] num = new int[n];
System.out.println("按照递增的顺序输入数组的元素");
for (int i = 0; i < num.length; i++) {
num[i]= input.nextInt();
}
System.out.println("请输入你要查找的目标值");
int target = input.nextInt();
int[] result= searchRange(num,target);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
public static int[] searchRange(int []nums,int target) {
int length = nums.length;
int left = 0, right = length - 1;
int m = 0;
int min = 0, max = 0;
while (left <= right) {
m = (left + right) / 2;
if (nums[m] < target) {
left = m + 1;
} else if (nums[m] > target) {
right = m - 1;
} else {
max = m;
min = m;
while (true) {
//数组越界问题
if ((max+1)!=length&&nums[max + 1] == target) {
max++;
}
if ((min-1)!=-1&&nums[min - 1] == target) {
min--;
}
if (((min-1)==-1||nums[min - 1] != target) && ((max+1)==length||nums[max + 1] != target)) {
break;
}
}
int[] result = new int[]{min, max};
return result;
};
}
//第一次错误,漏掉了这个特殊情况
max=-1;
min=-1;
int[] result = new int[]{min, max};
return result;
}
}
关于滑动这个数组下标我这个还可以在进行优化,相比我的所用时间会更小
// 向左滑动,找左边界
while (left - 1 >= 0 && nums[left - 1] == nums[index]) { // 防止数组越界。逻辑短路,两个条件顺序不能换
left--;
}
// 向左滑动,找右边界
while (right + 1 < nums.length && nums[right + 1] == nums[index]) { // 防止数组越界。
right++;
}
return new int[] {left, right};
双二分法确定上下边界
class Solution {
int[] searchRange(int[] nums, int target) {
int leftBorder = getLeftBorder(nums, target);
int rightBorder = getRightBorder(nums, target);
// 情况一
if (leftBorder == -2 || rightBorder == -2) return new int[]{-1, -1};
// 情况三
if (rightBorder - leftBorder > 1) return new int[]{leftBorder + 1, rightBorder - 1};
// 情况二
return new int[]{-1, -1};
}
int getRightBorder(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int rightBorder = -2; // 记录一下rightBorder没有被赋值的情况
while (left <= right) {
int middle = left + ((right - left) / 2);
if (nums[middle] > target) {
right = middle - 1;
} else { // 寻找右边界,nums[middle] == target的时候更新left
left = middle + 1;
rightBorder = left;
}
}
return rightBorder;
}
int getLeftBorder(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int leftBorder = -2; // 记录一下leftBorder没有被赋值的情况
while (left <= right) {
int middle = left + ((right - left) / 2);
if (nums[middle] >= target) { // 寻找左边界,nums[middle] == target的时候更新right
right = middle - 1;
leftBorder = right;
} else {
left = middle + 1;
}
}
return leftBorder;
}
}
本文作者:TranquilGlow
本文链接:https://www.cnblogs.com/xuehaiqiule/p/17621640.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步