LeetCode(34):搜索范围

Medium!

题目描述:

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

你的算法时间复杂度必须是 O(log n) 级别。

如果数组中不存在目标值,返回 [-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]

解题思路:

这道题让我们在一个有序整数数组中寻找相同目标值的起始和结束位置,而且限定了时间复杂度为O(logn),这是典型的二分查找法的时间复杂度,所以这道题也需要用此方法,我们的思路是首先对原数组使用二分查找法,找出其中一个目标值的位置,然后向两边搜索找出起始和结束的位置,代码如下:

C++解法一:

复制代码
 1 class Solution {
 2 public:
 3     vector<int> searchRange(vector<int>& nums, int target) {
 4         int idx = search(nums, 0, nums.size() - 1, target);
 5         if (idx == -1) return {-1, -1};
 6         int left = idx, right = idx;
 7         while (left > 0 && nums[left - 1] == nums[idx]) --left;
 8         while (right < nums.size() - 1 && nums[right + 1] == nums[idx]) ++right;
 9         return {left, right};
10     }
11     int search(vector<int>& nums, int left, int right, int target) {
12         if (left > right) return -1;
13         int mid = left + (right - left) / 2;
14         if (nums[mid] == target) return mid;
15         else if (nums[mid] < target) return search(nums, mid + 1, right, target);
16         else return search(nums, left, mid - 1, target);
17     }
18 };
复制代码

可能有些人会觉得上面的算法不是严格意义上的O(logn)的算法,因为在最坏的情况下会变成O(n),比如当数组里的数全是目标值的话,从中间向两边找边界就会一直遍历完整个数组,那么我们下面来看一种真正意义上的O(logn)的算法,使用两次二分查找法,第一次找到左边界,第二次调用找到右边界即可。

C++解法二:

复制代码
 1 class Solution {
 2 public:
 3     vector<int> searchRange(vector<int>& nums, int target) {
 4         vector<int> res(2, -1);
 5         int left = 0, right = nums.size() - 1;
 6         while (left < right) {
 7             int mid = left + (right - left) / 2;
 8             if (nums[mid] < target) left = mid + 1;
 9             else right = mid;
10         }
11         if (nums[right] != target) return res;
12         res[0] = right;
13         right = nums.size();
14         while (left < right) {
15             int mid = left + (right - left) / 2;
16             if (nums[mid] <= target) left = mid + 1;
17             else right= mid;
18         }
19         res[1] = left - 1;
20         return res;
21     }
22 };
复制代码

 

posted @   Ariel_一只猫的旅行  阅读(371)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示