算法leetcode|34. 在排序数组中查找元素的第一个和最后一个位置(rust重拳出击)

news/2024/11/15 3:23:53/

文章目录

  • 34. 在排序数组中查找元素的第一个和最后一个位置:
    • 样例 1:
    • 样例 2:
    • 样例 3:
    • 提示:
  • 分析:
  • 题解:
    • rust
    • go
    • c++
    • c
    • python
    • java


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]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

分析:

  • 面对这道算法题目,二当家的陷入了沉思。
  • 有序数组中查找元素,而且要求时间复杂度为 O(log n) ,那肯定要用二分查找法了,但是题目要找两个位置,所以我们需要两次二分查找,可是结果要一头一尾,逻辑不一样,难道写两个二分吗?其实可以复用,我们实现一个查找指定元素的第一个位置,但是多一个参数来传递是否包含相等元素,所以结果中查找元素的第一个位置,就是二分查找大于等于指定元素的第一个位置,结果中查找元素的最后一个位置,就是二分查找大于指定元素的第一个位置再减一。

题解:

rust

impl Solution {pub fn search_range(nums: Vec<i32>, target: i32) -> Vec<i32> {fn binary_search(nums: &Vec<i32>, target: i32, include_eq: bool) -> usize {if nums.is_empty() {return 0;}let (mut left, mut right, mut ans) = (0, nums.len() - 1, nums.len());while left <= right {let mid = (left + right) >> 1;if nums[mid] > target || (include_eq && nums[mid] == target) {ans = mid;if mid == 0 {break;}right = mid - 1;} else {left = mid + 1;}}return ans;}let left_idx = binary_search(&nums, target, true);let right_idx = binary_search(&nums, target, false) - 1;if left_idx <= right_idx && right_idx < nums.len() && nums[left_idx] == target && nums[right_idx] == target {return vec![left_idx as i32, right_idx as i32];}return vec![-1, -1];}
}

go

func searchRange(nums []int, target int) []int {leftIdx := sort.SearchInts(nums, target)if leftIdx == len(nums) || nums[leftIdx] != target {return []int{-1, -1}}rightIdx := sort.SearchInts(nums, target+1) - 1return []int{leftIdx, rightIdx}
}

c++

class Solution {
public:vector<int> searchRange(vector<int> &nums, int target) {int leftIdx = lower_bound(nums.begin(), nums.end(), target) - nums.begin();int rightIdx = lower_bound(nums.begin(), nums.end(), target + 1) - nums.begin() - 1;if (leftIdx <= rightIdx && rightIdx < nums.size() && nums[leftIdx] == target && nums[rightIdx] == target) {return vector<int>{leftIdx, rightIdx};}return vector<int>{-1, -1};}
};

c

int binarySearch(int* nums, int numsSize, int target, bool includeEq) {int left = 0, right = numsSize - 1, ans = numsSize;while (left <= right) {int mid = (left + right) >> 1;if (nums[mid] > target || (includeEq && nums[mid] == target)) {right = mid - 1;ans = mid;} else {left = mid + 1;}}return ans;
}/*** Note: The returned array must be malloced, assume caller calls free().*/
int* searchRange(int* nums, int numsSize, int target, int* returnSize){int leftIdx = binarySearch(nums, numsSize, target, true);int rightIdx = binarySearch(nums, numsSize, target, false) - 1;int *ans = malloc(sizeof(int) * 2);*returnSize = 2;if (leftIdx <= rightIdx && rightIdx < numsSize && nums[leftIdx] == target && nums[rightIdx] == target) {ans[0] = leftIdx, ans[1] = rightIdx;} else {ans[0] = -1, ans[1] = -1;}return ans;
}

python

class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:def binary_search(include_eq: bool):left, right, ans = 0, len(nums) - 1, len(nums)while left <= right:mid = (left + right) >> 1if nums[mid] > target or (include_eq and nums[mid] == target):right = mid - 1ans = midelse:left = mid + 1return ansleft_idx = binary_search(True)right_idx = binary_search(False) - 1if left_idx <= right_idx < len(nums) and nums[left_idx] == target and nums[right_idx] == target:return [left_idx, right_idx]return [-1, -1]

java

class Solution {public int[] searchRange(int[] nums, int target) {int leftIdx = binarySearch(nums, target, true);int rightIdx = binarySearch(nums, target, false) - 1;if (leftIdx <= rightIdx && rightIdx < nums.length && nums[leftIdx] == target && nums[rightIdx] == target) {return new int[]{leftIdx, rightIdx};} return new int[]{-1, -1};}private int binarySearch(int[] nums, int target, boolean includeEq) {int left = 0, right = nums.length - 1, ans = nums.length;while (left <= right) {int mid = (left + right) >> 1;if (nums[mid] > target || (includeEq && nums[mid] == target)) {right = mid - 1;ans = mid;} else {left = mid + 1;}}return ans;}
}

非常感谢你阅读本文~
欢迎【点赞】【收藏】【评论】~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~



http://www.ppmy.cn/news/21336.html

相关文章

【vue2】vuex基础与五大配置项

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;vuex基础认识、state、getters、mutations actions、modules使用 目录(文末原素材) 一、…

【面试】vue组件style中scoped的作用是什么?什么是scoped穿透?

vue组件style中scoped的作用是什么&#xff1f; 在Vue文件中的style标签上有一个特殊的属性——scoped。scoped属性是 HTML5 中的新属性&#xff0c;是一个布尔属性&#xff0c;如果使用该属性&#xff0c;则css样式仅仅只能应用到当前的Vue组件&#xff0c;避免组件之间样式相…

个人简历(前端)

简历导航个人基本信息为了节约你的时间&#xff0c;请先看这一段我能为公司提供一个什么样的程序员我会的和我不会的个人经历和个人想法工作履历关于我在上一家公司“创业”个人基本信息 标题信息姓名保密性别男学历本科&#xff08;浙工商计算机专业&#xff09;工作经验6年技…

docker run、exec和attach使用和区别

结论 docker run&#xff1a;创建和启动一个新的容器实例&#xff0c;操作对象是镜像&#xff0c;选项较多&#xff0c;如果你要创建和启动一个容器&#xff0c;只能用run&#xff1b;docker exec&#xff1a;在已运行的容器中&#xff0c;执行命令&#xff0c;操作对象是容器&…

【MyBatis持久层框架】配置文件实现增删改查实战案例(下)

前言 前面我们学习了 MyBatis 持久层框架的原生开发方式和 Mapper 代理开发两种方式&#xff0c;解决了使用 JDBC 基础性代码操作数据库时存在的硬编码和操作繁琐的问题。 在配置文件实现增删改查上篇中&#xff0c;我们详细讲解了常用的查询操作&#xff0c;例如查询所有数据…

model.train()与model.val()

一、问题描述 需要将mmpose框架下训练的模型单独保存出来&#xff0c;做后续处理。用torch.save()直接保存模型mmpose_model.pt&#xff0c;然后重新搭建模型&#xff0c;把保存的模型参数加载进去&#xff0c;得到scratch_model.pt使用scratch_model.pt进行推理&#xff0c;与…

界面组件DevExtreme v22.2亮点——UI模板库升级换代!

DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET Core&#xff0c;jQuery&#xff0c;Knockout等&#xff09;构建交互式的Web应用程序。从Angular和Reac&#xff0c…

Java线程池中的execute和submit

一、概述 execute和submit都是线程池中执行任务的方法。 execute是Executor接口中的方法 public interface Executor {void execute(Runnable command); }submit是ExecuteService接口中的方法。 public interface ExecutorService extends Executor {<T> Future<T…