[Algorithm and Data Structure] 34. LeetCode finds the first and last position of an element in a sorted array

For all the LeetCode solution indexes, you can read this article - [Algorithm and Data Structure] LeetCode Solution .

topic

insert image description here

1. Violent Poor Solution

  Idea analysis: Seeing problems such as searching for arrays, the brute force solution can generally be solved, so we first call the library function find() to find the left boundary, and then start from the left boundary to find the right boundary (left=right),Here we should pay attention to a special case, that is, the left boundary is equal to the end index of the array. At this time, the right boundary is equal to the left boundary and can be returned directly. The remaining situation is that the while loop finds the first index that is not equal to the value of the target, this is the right boundary (excluding target), and the right boundary is subtracted by 1 when returning. If not found, then right itself is the right boundary.

	// 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};
		}
	}

  Compared with other people's algorithms: the speed is slightly slower, and the memory usage is large.
Complexity Analysis

  • time complexity: O ( n ) O(n)O ( n ) , worst case iterating over the entire array.
  • Space complexity:O(1) O(1)O ( 1 ) , the memory occupied by the runtime is a constant.
    insert image description here

Two, dichotomy

  Idea analysis: Reading the title, we can draw three situations:

  • 1. The target is not in the array, return {-1, -1}.
  • 2. Target is in the array, normally returns {left, right}.
  • 3. Target is in the array, some special cases.

  In the first case, the ordinary dichotomy can be used. In the second case, first find the index middle of the target, and then extend to both sides to find the boundary value, so how to extend it?

  We also use the while loop to find the boundary value. First, we must limit the range of the left and right boundary indexes. For example, the left boundary must be greater than 0, and the right boundary must be smaller than the array capacity.. The index keeps changing until the value of the array is not equal to the target, and we find the boundary value. Normally, we can find the boundary value not equal to the target, then return {left +1, right - 1 }. The third is a special case, when no boundary value not equal to target is found, the boundary value index itself is returned.

	// 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 };
	}

Complexity Analysis

  • time complexity: O ( n ) O(n)O ( n ) , although the dichotomy method is used, the actual time complexity does not meet the requirements of the topic. In essence, it relies on the while loop to find the boundary value. The worst case is to traverse the entire array, and the follow-up needs to be improved.
  • Space complexity:O(1) O(1)O ( 1 ) , pinned memory.

  Algorithm comparison: Compared with the violent poor solution, the speed and memory are greatly improved.
insert image description here

full code

// 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

Guess you like

Origin blog.csdn.net/qq_45765437/article/details/130884363