介绍
标签:数组、二分查找
34. 在排序数组中查找元素的第一个和最后一个位置
难度 中等
34. 在排序数组中查找元素的第一个和最后一个位置
https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
题目
给定一个按照升序排列的整数数组 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
记录一个适合带有重复数组的二分查找模板
解题思路
方法一:
拿到手上第一反应就是个一次遍历
心想 O(n) 也不至于慢吧
2ms,15%,那没事了,还是二分查找吧
方法二:
题目要求O(log n),那很明显就是用二分查找
最主要的就是判断mid点是否满足条件
官方那种查找就很适合,就是在35题里面的那种
//官方在35题里面给的二分查找的示例
public int binarySearch(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n - 1, ans = n;
while (left <= right) {
int mid = ((right - left) >> 1) + left;
if (target <= nums[mid]) {
ans = mid;
right = mid - 1;
}
else {
left = mid + 1;
}
}
return ans;
}
代码
O(n) 代码
class Solution {
public int[] searchRange(int[] num, int target) {
int a = -1, b = -1;
for(int i = 0; i < num.length; ++i)
{
if((i == 0 && num[i] == target) || (i > 0 && num[i] == target && num[i-1] != target))
a = i;
if((i == num.length - 1 && num[i] == target) || (i < num.length && num[i] == target && num[i+1] != target))
b = i;
}
return new int[]{a, b};
}
}
两毫秒也是15%
O(log n) 代码
class Solution {
public int[] searchRange(int[] nums, int target) {
int leftIndex = binarySearch(nums, target, true);
int rigthIndex = binarySearch(nums, target, false) - 1;
if(leftIndex <= rigthIndex && rigthIndex < nums.length && nums[leftIndex] == target && nums[rigthIndex] == target)
{
return new int[]{leftIndex, rigthIndex};
}
return new int[]{-1, -1};
}
//官方这个复用的二分查找真不错
public int binarySearch(int[] nums, int target, boolean lower) {
int left = 0;
int ans = nums.length;
int right = ans - 1;
while(left <= right)
{
int mid = (left + right) / 2;
//大于与大于等于的差距就是在于是否包含target,在仅大于的情况下就是在找target后面的那位数
if (nums[mid] > target || (lower && nums[mid] >= target))
{
ans = mid;
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return ans;
}
}