【算法与数据结构】34、 LeetCode在排序数组中查找元素的第一个和最后一个位置

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解

题目

在这里插入图片描述

一、暴力穷解法

  思路分析:看到查找数组这类题目,暴力穷解法一般都可以解决,那么我们首先调用库函数find()找到左边界,然后从左边界出发找右边界(left=right),这里要注意一个特殊的情况,就是左边界等于数组末端索引。这时候右边界等于左边界,可以直接返回。剩下的情况就是while循环找到第一个不等于target的值的索引,这个就是右边界(不包含target),返回时右边界要减去1。如果找不到,那么right本身就是右边界。

	// 1、暴力穷解法
	vector<int> searchRange2(vector<int>& nums, int target) {
    
    
		auto it = find(nums.begin(), nums.end(), target);   // 返回索引
		if (it == nums.end()) {
    
    
			return {
    
     -1, -1 };
		}
		else {
    
    	
			int left = it - nums.begin();			// 左边界
			int right = left;
			if (left != nums.size() - 1) {
    
    
				while (right < (nums.size() - 1) && nums[++right] == target);		// 右边界
			}
			return {
    
    left, nums[right] != target ? right - 1 : right};
		}
	}

  和其他人的算法比较:速度稍微慢了点,而且内存占用多。
复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),最坏的情况下要遍历整个数组。
  • 空间复杂度: O ( 1 ) O(1) O(1),运行时占用的内存是一个常数。
    在这里插入图片描述

二、二分法

  思路分析:阅读题目我们可以得出三种情况:

  • 1.target不在数组内,返回{-1, -1}。
  • 2.target在数组内, 正常返回{ left, right}。
  • 3.target在数组内,一些特殊情况。

  第一种情况使用普通的二分法就可以搞定,第二种先找到target的索引middle,然后向两边延伸找到边界值,那么如何延伸呢?

  我们同样使用while循环找到边界值,首先要限定左右边界索引的范围,比如左边界必须大于0,右边界必须小于数组容量。索引不断变换,直到数组的值不等于target,我们就找到边界值,正常的情况是能够找到不等于target的边界值,那么返回{left +1, right - 1 }就可以。第三种就是特殊情况,当找不到不等于target的边界值时,返回边界值索引本身。

	// 2、二分法
	vector<int> searchRange(vector<int>& nums, int target) {
    
    
		int left = 0, right = nums.size() - 1, middle = 0;
		while (left <= right) {
    
    
			middle = (left + right) / 2;
			if (nums[middle] < target) {
    
    
				left = middle + 1;
			}
			else if (nums[middle] > target) {
    
    
				right = middle - 1;
			}
			else {
    
    
				left = middle;
				right = middle;
				while (right < (nums.size() - 1) && nums[++right] == target );
				while (left > 0 && nums[--left] == target);
				return {
    
     nums[left] != target ? left + 1 : left, nums[right] != target ? right - 1 : right };
			}
		}
		return {
    
     -1, -1 };
	}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),虽然用了二分法,但是实际时间复杂度没有达到题目要求,本质上是靠while循环找到边界值,最坏的情况就是遍历整个数组,后续有待改进。
  • 空间复杂度: O ( 1 ) O(1) O(1),固定内存。

  算法对比:较之暴力穷解法,速度和内存方面都有很大提升。
在这里插入图片描述

完整代码

// 34. 在排序数组中查找元素的第一个和最后一个位置
# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;

class Solution {
    
    
public:
	// 1、暴力穷解法
	vector<int> searchRange2(vector<int>& nums, int target) {
    
    
		auto it = find(nums.begin(), nums.end(), target);   // 返回索引
		if (it == nums.end()) {
    
    
			return {
    
     -1, -1 };
		}
		else {
    
    	
			int left = it - nums.begin();			// 左边界
			int right = left;
			if (left != nums.size() - 1) {
    
    
				while (right < (nums.size() - 1) && nums[++right] == target);		// 右边界
			}
			return {
    
    left, nums[right] != target ? right - 1 : right};
		}
	}

	// 2、二分法
	vector<int> searchRange(vector<int>& nums, int target) {
    
    
		int left = 0, right = nums.size() - 1, middle = 0;
		while (left <= right) {
    
    
			middle = (left + right) / 2;
			if (nums[middle] < target) {
    
    
				left = middle + 1;
			}
			else if (nums[middle] > target) {
    
    
				right = middle - 1;
			}
			else {
    
    
				left = middle;
				right = middle;
				while (right < (nums.size() - 1) && nums[++right] == target );
				while (left > 0 && nums[--left] == target);
				return {
    
     nums[left] != target ? left + 1 : left, nums[right] != target ? right - 1 : right };
			}
		}
		return {
    
     -1, -1 };
	}
};

void my_print(vector<int>& v, string msg)
{
    
    
	cout << msg << endl;
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
    
    
		cout << *it << ' ';
	}
	cout << endl;
}

int main()
{
    
    
	int target = 8;
	int arr[] = {
    
     5, 7, 7, 8, 8, 10 };
	vector<int> nums;
	Solution s1;
	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
    
    
		nums.push_back(arr[i]);
	}
	my_print(nums, "目标数组:");
	vector<int> index = s1.searchRange(nums, target);
	my_print(index, "查找结果:");
	system("pause");
	return 0;
}

end

猜你喜欢

转载自blog.csdn.net/qq_45765437/article/details/130884363