「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」
34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 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]
复制代码
暴力破解
思路 由题意知道,需要查找首位和末尾的目标值,那么我们可以在遍历数组nums的过程中,去对比每一个元素是否为target值
具体步骤:
- 声明结果res = [-1,-1],遍历nums
- 如果找到target,且res[0] 为-1 ,那么更新res[0] = i 否则只更新res[1]的值即可
最后返回res即可
var searchRange = function(nums, target) {
var res = [-1,-1]
for(var i = 0;i < nums.length ; i++){
if(nums[i]===target){
if(res[0]===-1){
res[0] = i
res[1] = i
}else{
res[1] = i
}
}
}
return res
};
复制代码
二分查找
思路
暴力破解没有利用到nums数组是有序排列的这个条件,其实我们可以用二分查找的方式更快的找到target的位置
具体实现:
- 声明结果res = [-1,-1],声明left和right为数组两端的两个值
- while循环条件left<=right,找到重点位置mid
- 如果nums[mid]小于target那么left = mid+1
- 如果nums[mid]大于等于target那么right = mid-1
这样循环下去最后left一定会定位在第一个target的位置
但是目标可能有多个值,所以我们需要再次while循环以找到target的末位置
- while循环条件nums[left] === target,那么我们就可以更新一下res[1]的值,并且left++,往后延伸直到nums[left]不再符合条件
那么此时res中便记录了target的首尾位置信息,返回res即可
var searchRange = function (nums, target) {
// 二分查找
var res = [-1, -1]
var left = 0
var right = nums.length
while (left <= right) {
var mid = (left + right) >> 1
if (nums[mid] < target) {
left = mid + 1
} else {
right = mid - 1
}
}
// 如果res 不等于[-1,-1] 那么left为target的起始位置
while (nums[left] === target) {
if (res[0] === -1) res[0] = left
res[1] = left
left++
}
return res
};
复制代码