腾讯&字节&leetcode34:在排序数组中查找元素的第一个和最后一个位置
sisterAn opened this issue · comments
瓶子君 commented
给定一个按照升序排列的整数数组 nums
,和一个目标值 target
。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(logn)
级别。
如果数组中不存在目标值,返回 [-1, -1]
。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
附赠leetcode地址:leetcode
Cxy56 commented
var searchRange = function(nums, target) {
let left = 0, right = nums.length -1
let start = -1, end = -1
while(left <= right) {
if(nums[left] < target) left++
// 找到第一个出现的位置,赋值给start
if(nums[left] === target && start === -1) start = left++
if(nums[right] > target) right--
// 找到最后一个出现的位置,赋值给end
if(nums[right] === target && end === -1) end = right--
if(start > -1 && end > -1) break
}
return [start, end]
};
瓶子君 commented
解答一:findIndex、lastIndexOf
findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。
lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。
解答二:二分查找
let searchRange = function(nums, target) {
return [leftSearch(nums, target), rightSearch(nums, target)]
}
let leftSearch = function(nums, target) {
let low = 0,
high = nums.length - 1,
mid
while (low <= high) {
mid = Math.floor((low+high)/2)
if (nums[mid] < target) {
low = mid + 1
} else if (nums[mid] > target) {
high = mid - 1
} else if (nums[mid] === target) {
// 这里不返回,继续收缩左侧边界
high = mid - 1
}
}
// 最后检查 low 是否越界或命中
if (low >= nums.length || nums[low] != target)
return -1
return low
}
let rightSearch = function (nums, target) {
let low = 0,
high = nums.length - 1,
mid
while (low <= high) {
mid = Math.floor((low+high)/2)
if (nums[mid] < target) {
low = mid + 1
} else if (nums[mid] > target) {
high = mid - 1
} else if (nums[mid] === target) {
// 这里不返回,继续收缩右侧边界
low = mid + 1
}
}
// 最后检查 high 是否越界或命中
if (high < 0 || nums[high] != target)
return -1
return high
}
复杂度分析:
- 时间复杂度:O(logn)
- 空间复杂度:O(1)
Airfald commented
嗯,这算法可以, 但是在真正项目中我愿意用 findIndex , findLastIndex
demo commented
### const comfiles = (arr, val) => {
let sta = -1, end = -1;
let obj = {}
arr.forEach((item, index) => {
if (item === val) {
if (obj[item]) {
end = index
} else {
obj[item] = index
sta = index
}
}
})
return [sta, end]
}
JYone223 commented
简化的二分查找
var searchRange = function(nums, target) {
let mid;
let low = 0;
let high = nums.length - 1;
while (low <= high) {
mid = Math.floor((low + high) / 2);
if (nums[mid] === target) {
let start = end = mid;
while (nums[start] === target) start--;
while (nums[end] === target) end++;
return [start + 1, end - 1];
}
if (nums[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return [-1, -1];
}
KylinLee commented
二分查找找到后,双指针同时向前向后查找。