你下班了,是立刻回家还是会再待一会?相信大家肯定都是马上飞奔回家吧,再待一会干嘛,上班上出瘾了吗?然而,一网友就发帖提问:为什么公司那么多同事(尤其是Leader),晚上宁愿在工位刷抖音也不下班回家呢?
帖子下面,热爱评论的宝子们为我们解惑了。有人直接说:“据观察,有的是不想回家带小孩儿,有的是单身狗不想回狭小的出租屋”
还有人说:“因为回家只有空荡荡的房间 在公司省电费”区区几个字,越看越心酸。
另一边,还有人开玩笑:“等着家里老婆完事,不想回去撞到尴尬。”啊这...
更有人直言:“我之前问过我们公司一个领导,他跟我说等我到了他那个年纪,你就知道了”
这也反映出了一种生活状态:在外面各种当牛马,回家还要面对各种压力,所以,不回家就成了最简单的逃避方式。
但不管怎样,生活还得继续,希望大家都能找到属于自己的调味剂。毕竟,生活不止眼前的苟且,还有诗和远方,不是吗?那么你们觉得又是为什么呢?
下面是今日的大厂算法题
今日算法题,来自LeetCode的第34题:在排序数组中查找元素的第一个和最后一个位置,下面是我的算法思路及实现,让我们来看看吧。
算法题目
给定一个按照升序排列的整数数组 nums 和一个目标值 target,找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法。
👉点击领取 Go后端开发资料合集
算法思路
本题可以通过二分查找算法进行两次查找来解决:
第一次二分查找定位到目标值的开始位置:
如果 mid 对应的值大于或等于 target,移动右边界 right 到 mid。
否则,移动左边界 left 到 mid + 1。
最终,左边界 left 将指向目标值的开始位置。
第二次二分查找定位到目标值的结束位置: 如果 mid 对应的值小于或等于 target,移动左边界 left 到 mid + 1。
否则,移动右边界 right 到 mid。
最终,右边界 right 将指向目标值的结束位置的下一个位置,所以目标值的结束位置实际上是 right - 1。
在每次查找过程中,都需要检查边界条件,确保不会出现越界的情况。
func searchRange(nums []int, target int) []int {
findFirstPosition := func() int {
left, right := 0, len(nums)-1
for left <= right {
mid := left + (right-left)/2
if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
if left < len(nums) && nums[left] == target {
return left
}
return -1
}
findLastPosition := func() int {
left, right := 0, len(nums)-1
for left <= right {
mid := left + (right-left)/2
if nums[mid] <= target {
left = mid + 1
} else {
right = mid - 1
}
}
if right >= 0 && nums[right] == target {
return right
}
return -1
}
return []int{findFirstPosition(), findLastPosition()}
}
Java实现
public int[] searchRange(int[] nums, int target) {
int[] result = new int[]{-1, -1};
result[0] = findFirstPosition(nums, target);
result[1] = findLastPosition(nums, target);
return result;
}
private int findFirstPosition(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] >= target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
if (left < nums.length && nums[left] == target) return left;
return -1;
}
private int findLastPosition(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] <= target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if (right >= 0 && nums[right] == target) return right;
return -1;
}
JavaScript实现
function searchRange(nums, target) {
function findFirstPosition() {
let left = 0, right = nums.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (nums[mid] >= target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
if (nums[left] === target) return left;
return -1;
}
function findLastPosition() {
let left = 0, right = nums.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (nums[mid] <= target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if (nums[right] === target) return right;
return -1;
}
return [findFirstPosition(), findLastPosition()];
}
算法解析
这种方法利用了二分查找的高效查找能力,在对数组进行两次二分查找后,能够精确地找到目标值的开始和结束位置。
通过调整左右边界的移动策略,我们可以分别定位到目标值的首次和最后一次出现的位置,从而实现了在 O(log n) 时间复杂度内解决问题的目标。
对于数组 nums = [5,7,7,8,8,10] 和目标值 target = 8:
第一次查找定位到开始位置,结果为 3。
第二次查找定位到结束位置,结果为 4。
因此,函数返回 [3, 4]。
因此,在使用二分查找之前,应先考虑数据是否满足这一条件,或者是否有必要先进行排序。同时,也要考虑排序本身的成本是否可接受,因为在某些情况下,排序的时间复杂度可能会抵消二分查找带来的效率提升。
![]()
热门推荐
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。