Второе по величине число в массиве

Вопрос или проблема

Дана массив arr, верните второй по величине уникальный элемент из массива. Если второго по величине элемента не существует, верните -1.

Я пытался найти второй по величине элемент в массиве. Может кто-нибудь объяснить, где я ошибся?

int getSecondLargest(vector<int> &arr) {
    // Код здесь
    int max = 0;
    int smax = 0;
    int ans = -1;
    for(int i =0; i<arr.size(); i++){
        if(arr[i]>max){
            max = arr[i];
        }
    }
    for(int i =0; i<arr.size(); i++){
        if(arr[i]<max){
            smax = arr[i];
        }
    }
    for(int i=0; i<arr.size(); i++){
        if(arr[i]>smax && arr[i]<max){
            smax = arr[i];
        }
    }
    if(max != smax){
        return smax;
    }
    if(max == smax){
        return ans;
    }
}

Здесь код не дает никакого вывода, когда в массиве нет второго по величине элемента.

int getSecondLargest(vector<int> &arr) {
    if(arr.size() < 2) return -1;

    int max = INT_MIN, smax = INT_MIN;

    for(int i = 0; i < arr.size(); i++) {
        if(arr[i] > max) {
            smax = max;
            max = arr[i];
        } else if(arr[i] > smax && arr[i] < max) {
            smax = arr[i];
        }
    }

    return (smax == INT_MIN) ? -1 : smax;
}

Пройдите по массиву один раз. Если arr[i] больше max, обновите и max, и smax. Если arr[i] находится между smax и max, обновите smax. Если второго уникального по величине элемента не существует, верните -1.

Вам нужно инициализировать максимальное значение минимально возможным значением для используемого типа, поэтому вы можете использовать std::numeric_limits<int>::min()

Этот участок кода вернет это значение, если второго максимума нет:

#include <vector>
#include <limits>
#include <iostream>

using namespace std;

int getSecondLargest (vector<int> const& arr) 
{
    // Код здесь
    int  max = std::numeric_limits<int>::min();
    int smax = std::numeric_limits<int>::min();

    for(int i =0; i<arr.size();i++)
    {
        if (arr[i]>max) { max = arr[i]; }
    }

    for(int i =0; i<arr.size(); i++) 
    {
        if (arr[i]>smax and arr[i]<max) { smax = arr[i]; }
    }

    return smax;
}

int main() 
{
    cout << getSecondLargest ({ 1,2,3,4,5,6,7 }) << "\n";
    cout << getSecondLargest ({ 7,6,5,4,3,2,1 }) << "\n";
    cout << getSecondLargest ({ 4,5,6,1,2,9,0 }) << "\n";
    cout << getSecondLargest ({ 7,7           }) << "\n";
    cout << getSecondLargest ({               }) << "\n";
}

Демо

Вместо готового решения я предложу идею о том, как решить это с помощью итераторов.

  • Начните с того, чтобы сделать два итератора (здесь называемых largest и second) и укажите их на первые два уникальных элемента. Если не найдено два уникальных элемента, верните итератор end.
  • Пройдите по оставшемуся диапазону в поисках элементов, больших чем второй по величине, найденный на данный момент, и замените соответствующий итератор.
template <class It>
It getSecondLargest(It begin, It end) {
    if (begin == end) return end;  // нет элементов, верните итератор end
    auto largest = begin;

    // ищем первый элемент, не равный *largest:
    do {
        ++begin;
        if (begin == end) return end;  // не найден такой элемент
    } while (*begin == *largest);

    auto second = begin;

    // меняем их местами, если необходимо:
    if (*largest < *second) std::swap(second, largest);

    // проверяем, есть ли другие большие элементы
    for (++begin; begin != end; ++begin) {
        if (*second < *begin) {
            if (*largest < *begin) {  // еще больше?
                second = largest;     // второй теперь ранее наибольший
                largest = begin;      // и у нас новый наибольший
            } else if (*begin < *largest) {  // не дубликат наибольшего?
                second = begin;       // тогда у нас новый второй по величине
            }
        }
    }
    return second;
}

Ответ или решение

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

Решение

Алгоритм

  1. Проверка на пустоту: Если массив содержит меньше двух элементов, вернуть -1, так как второго максимума не может быть.
  2. Инициализация: Используем переменные для хранения максимального (max) и второго максимального (smax) значения. Инициализируем их минимально возможными значениями для целого типа int, используя std::numeric_limits<int>::min().
  3. Перебор элементов массива:
    • Если текущий элемент больше, чем max, мы обновляем smax значением max, а max – текущим элементом.
    • Если текущий элемент находится между smax и max, обновляем smax текущим элементом.
  4. Проверка на существование второго максимального элемента: Если smax после завершения проверки остается равным std::numeric_limits<int>::min(), возвращаем -1, указывая на отсутствие второго максимума.
  5. Возврат результата: Если всё прошло успешно, возвращаем значение smax.

Код на C++

#include <vector>
#include <limits>
#include <iostream>

using namespace std;

int getSecondLargest(const vector<int>& arr) {
    if (arr.size() < 2) return -1; // Если массив содержит менее 2 элементов, возврат -1.

    int max = numeric_limits<int>::min();
    int smax = numeric_limits<int>::min();

    for(int i = 0; i < arr.size(); i++) {
        if (arr[i] > max) { 
            smax = max; // Обновляем второй максимум.
            max = arr[i]; // Обновляем максимум.
        } else if (arr[i] > smax && arr[i] < max) {
            smax = arr[i]; // Обновляем второй максимум, если элемент между max и smax.
        }
    }

    return (smax == numeric_limits<int>::min()) ? -1 : smax; // Если нет второго максимума, возврат -1.
}

int main() {
    cout << getSecondLargest({1, 2, 3, 4, 5, 6, 7}) << "\n"; // Ожидаем 6
    cout << getSecondLargest({7, 6, 5, 4, 3, 2, 1}) << "\n"; // Ожидаем 6
    cout << getSecondLargest({4, 5, 6, 1, 2, 9, 0}) << "\n"; // Ожидаем 6
    cout << getSecondLargest({7, 7}) << "\n"; // Ожидаем -1
    cout << getSecondLargest({}) << "\n"; // Ожидаем -1
}

Примечания

  • Этот подход использует один проход по массиву, что делает его эффективным с точки зрения времени выполнения – O(n), где n – количество элементов в массиве.
  • Важно правильно обрабатывать случаи, когда массив содержит все одинаковые элементы или его длина меньше двух. В этих случаях алгоритм корректно вернет -1.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...