这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战
在排序数组中查找元素的第一个和最后一个位置
该题出自力扣的34题 —— 在排序数组中查找元素的第一个和最后一个位置【中等题】
审题
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶: 你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
- 从题意就是简单题的意思,给出一个有序数组,并且找出其中的目标元素的下标,目标元素可能不止存在一个,所以返回一个数组,存出现的第一个和最后一个。
- 实现方式也很多,但是需要注意题意最后的进阶,用时间复杂度O(log n)
- 简单粗暴for循环
- 直接for循环,用两个变量分别记录下标
- 时间复杂度O(n),遍历整个数组
- 因为是有序数组,所以大可不必用到遍历整个数组;二分查找更适合这种有序数组
- 判断数组是否为空
- 用两个变量统计下标,下标是目标数的第一个和最后一个。
- 调用二分方法
- 二分方法 稍微调整,返回目标数的下一位初次出现位置
编码
- 暴力循环
public int[] searchRange(int[] nums, int target) {
int[] a = new int[]{-1,-1};
if (nums.length == 0)return a;
for (int i = 0;i<nums.length;i++) {
if (nums[i] == target && a[0] == -1)a[0] = i;
if(nums[i] == target)a[1] = i;
}
return a;
}
- 二分查找
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] a = new int[]{-1,-1};
if (nums.length == 0)return a;
int left = binarySearch(nums,target-1);
int right = binarySearch(nums,target)-1;
if (right>=left && nums[left] == target){
a[0] = left;
a[1] = right;
}
return a;
}
public int binarySearch(int[] nums,int target){
int left = 0,right = nums.length -1,ans = nums.length;
while(right>=left){
int mid = left+(right - left)/2;
if (nums[mid] >target){
right = mid -1;
ans = mid;
}else {
left = mid +1;
}
}
return ans;
}
}
总结
对于二分的理解还不够娴熟,还是没有办法在看到题意的时候冒出二分的想法,直到完成题目提交后,才醒悟过来。并且容易卡在对于二分的初步理解,也就是背模板,无法灵活变通,例如题意里面的查找下一位的最初位置,返回 mid;