Алгоритм LeetCode C++ Brush Questions-searchFirstLastEqualElement

Сегодняшний вопрос

Дан целочисленный массив nums в порядке возрастания и целевое значение target. Узнайте, где в массиве начинается данное целевое значение

и конечное положение. Временная сложность вашего алгоритма должна быть на уровне O(log n). Если целевое значение не существует в массиве, верните [-1, -1].

Пример 1:

Ввод: числа = [5,7,7,8,8,10], цель = 8
Вывод: [3,4]

Пример 2:

Ввод: числа = [5,7,7,8,8,10], цель = 6
Вывод: [-1,-1]

Идеи решения проблем:

Учитывая упорядоченный массив nums и числовое значение target, требуется найти индекс первого элемента, равный этому элементу в массиве
, и индекс последнего элемента, равный этому элементу.
Этот вопрос является классическим вариантом бинарного поиска. Существует 4 основных варианта бинарного поиска:

  1. Находит первый элемент, значение которого равно заданному значению
  2. Находит последний элемент, значение которого равно заданному значению
  3. Найдите первый элемент, больший или равный заданному значению
  4. Найти последний элемент меньше или равный заданному значению

Идеи решения проблемы для этого вопроса могут быть решены с использованием решений варианта 1 и варианта 2 соответственно. Или используйте метод варианта 1 один раз
, а затем вернитесь назад, чтобы найти последний элемент, равный заданному значению. Однако последний метод может уменьшить временную сложность
до O(n), потому что возможно, что n элементов в массиве совпадают с заданным элементом. (см. код реализации 4-х базовых вариантов)

Образец кода:

class searchFirstLastEqualElement{
    
    
public:
    vector<int> searchRange(vector<int>& nums, int target) {
    
    
        vector<int> res(-1,-1);
        if(nums.empty()) return res;
        int n = nums.size(),left = 0, right = n-1;
        while(left <= right)
        {
    
    
            int m = left + (right - left)/2;
            if(nums[m] > target){
    
    
                right = m - 1;
            }else if(nums[m] < target){
    
    
                left = m + 1;
            } else {
    
    
				if(m = 0 || num[m-1] != target) {
    
    
					res[0] = m;
					return res;
				}
				right = m - 1;
			}
        }
        
        while(left <= right)
        {
    
    
            int m = left + (right - left)/2;
            if(nums[m] > target){
    
    
                right = m - 1;
            }else if(nums[m] < target){
    
    
                left = m + 1;
            } else {
    
    
				if(m == n -1 || nums[m+1] != targrt) {
    
    
					res[1] = m;
					return res;
				}
				low = m + 1;
			}
        }

        return res;
    }
};

Предварительные знания: дихотомия

1. Посылка дихотомии

1. Массив является упорядоченным массивом
2. В массиве нет повторяющихся элементов (при наличии повторяющихся элементов индекс элемента, возвращаемый методом бинарного поиска, может быть не уникальным), что соответствует ситуации выше тема.

2. Содержание

Логика дихотомии очень проста, достаточно уточнить определение интервала.
В методе дихотомии обычно есть два определения интервалов: закрытый слева и закрытый справа [левый, правый] или закрытый слева и открытый справа [левый, правый].

(1) Слева закрыто Справа закрыто [слева, справа]
class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
        int left = 0;
        int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
        while (left <= right) {
    
     // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
    
    
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
    
    
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else {
    
     // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};
(2) Слева закрыто справа открыто [слева, справа)
class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
        int left = 0;
        int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
        while (left < right) {
    
     // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
    
    
                right = middle; // target 在左区间,在[left, middle)中
            } else if (nums[middle] < target) {
    
    
                left = middle + 1; // target 在右区间,在[middle + 1, right)中
            } else {
    
     // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};

Из приведенных выше двух ситуаций можно сказать, что это очень просто, это не что иное, как обратить внимание на то, закрыта ли правая граница и может ли она принимать значение.

おすすめ

転載: blog.csdn.net/u010196944/article/details/127609944