Как получить значение меньше INT_MIN?

#c

#c

Вопрос:

 class Solution {
public:
    int thirdMax(vector<int>amp; nums) 
    {
        int first = INT_MIN;
        int second = INT_MIN;
        int third = INT_MIN;
        
        for(int i=0; i<nums.size(); i  )
        {
            if(nums[i] > first)
            {
                third = second;
                second = first;
                first = nums[i];
            }
            else if(nums[i] > second amp;amp; nums[i] != first)
            {
                third = second;
                second = nums[i];
            }
            else if(nums[i] > third amp;amp; nums[i] != first amp;amp; nums[i] != second)
            {
                third = nums[i];
            }
        }
        
        if(third == INT_MIN)
            return first;
        else
            return third;
    }
};
  

Этот код предназначен для поиска третьего по величине числа, и если оно не существует, то возвращает первое по величине число. Большинство тестовых примеров выполнены успешно, но как мне использовать этот метод для
[1,2,-2147483648], где один из элементов массива сам по себе является INT_MIN ?

Комментарии:

1. Заголовок не соответствует вопросу. В заголовке требуется значение меньше, чем INT_MIN которое не может поместиться в int , но вопрос касается точного использования INT_MIN .

2. How to get a value less than INT_MIN? Используя подписанный тип с более широким диапазоном представимых значений, чем int .

3. Сформулируйте условие, основанное на количестве различных чисел, а не на их значениях.

4. Простой подход заключается в том, чтобы установить первые три значения из массива в качестве текущих максимумов. Затем вы можете упорядочить их и запустить свой цикл как обычно. Или рассмотрите возможность использования >= (вместо > того, которое вы используете в настоящее время), что, вероятно, в любом случае более правильно.

5. @paddy ИМХО, это лучшее решение, чем добавлять всю эту сложность к optional предложенным в ответах.

Ответ №1:

Вы могли бы избежать «наполнения» INT_MIN особым значением и вместо этого использовать std::optional . Этот класс предназначен для того, чтобы отличать случай «нет значения» или «пусто» от фактического значения.

С помощью опций вы можете выразить то, что вы на самом деле хотите явно проверить, т. Е. Не То, больше или меньше число INT_MIN , а скорее, есть ли у вас уже «первое по величине», «второе по величине» и т. Д.

 int third_highest(const::vector<int>amp; nums) 
{
    std::optional<int> highest[3];

    if (nums.empty()) { 
        throw std::invalid_argument("Expected a non-empty sequence of integers");
    }
    
    for(auto x : nums) {
        if (not highest[0].has_value()) { highest[0] = x; continue; }
        if (x > highest[0].value()) {
            highest[2] = highest[1];
            highest[1] = highest[0];
            highest[0] = x;
            continue;
        }
        if (not highest[1].has_value()) { highest[1] = x; continue; }
        if (x > highest[1].value()) {
            highest[2] = highest[1];
            highest[1] = x;
            continue;
        }
        if (not highest[2].has_value()) { highest[2] = x; continue; }
        if (x > highest[2].value()) {
            highest[2] = x;
            continue;
        }
    }
    return highest[2] ? highest[2].value() : highest[0].value(); 
}
  

… и на самом деле, это можно упростить и сократить еще больше, если вы перебираете highest значения; или если вы создаете highest небольшой вектор, размер которого постепенно увеличивается от 0 до 3.


PS — Вы не должны использовать «класс решения». Это плохая идея оборачивать функции в классы без причины.

Комментарии:

1. причина, вероятно, в том, что у leetcode есть такой шаблон для решений. Я не устаю объяснять читателям, что им лучше писать правильный код для тестирования и отладки (и только для отправки использовать шаблон)

2. @idclev463035818 Да, похоже, это так: leetcode.com/problems/third-maximum-number

3. @Bob__ к сожалению, у них есть a using namespace std; в скрытой части, что может привести ко всевозможным проблемам.

4. @idclev463035818: Интересно и грустно знать. Я думаю, они действительно учат вас быть 7331 h4x0r…

Ответ №2:

Я бы проверил, равен ли размер вектора < 3, вместо того, чтобы проверять, является ли третье значение INT_MIN

 if(nums.size() < 3)
            return first;
        else
            return third;
  

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

 class Solution {
public:
    int thirdMax(vector<int>amp; nums) 
    {
        int first = INT_MIN;
        int second = INT_MIN;
        int third = INT_MIN;
        int counter = 0;
        
        for(int i=0; i<nums.size(); i  )
        {
            if(nums[i] > first)
            {
                third = second;
                second = first;
                first = nums[i];
                counter  ;
            }
            else if(nums[i] > second amp;amp; nums[i] != first)
            {
                third = second;
                second = nums[i];
                counter  ;
            }
            else if(nums[i] > third amp;amp; nums[i] != first amp;amp; nums[i] != second)
            {
                third = nums[i];
                counter  ;
            }
        }
        
        if(counter < 3)
            return first;
        else
            return third;
    }
};
  

Комментарии:

1. Что, если вектор содержит только много значений, но только два разных?

Ответ №3:

Вам не нужно значение меньше INT_MIN . Не существует int меньшего, чем INT_MIN .

Ваша реальная проблема может быть решена путем сортировки вектора в порядке убывания (при условии, что у вас все в порядке с O(n log n) решением):

 #include <algorithm>
#include <vector>

int thirdMax(std::vector<int>amp; nums) {
    // trivial cases
    if (nums.size() == 0) return -42; // or throw an exception ?
    if (nums.size() == 1) return nums[0];
    // sort
    std::sort(nums.begin(),nums.end(),std::greater<int>());
    // third largest
    if (nums.size() > 2) return nums[2];
    // otherwise largest
    return nums[0];
}
  

Комментарии:

1. std::nth_element насколько я понимаю, здесь может быть более эффективно. но вам нужно будет проверить, что размер массива равен 3 или более.

2. @JHBonarius да, я думал добавить линейную версию. Текущий был сосредоточен только на простоте

3. @JHBonarius Если проблема, которую пытается решить OP, заключается в следующем , они упоминают разные числа.

4. @Bob__ хорошая мысль… Я опубликовал свое собственное решение для этого.

Ответ №4:

Я хочу предложить другое решение, чтобы использовать только отдельные значения, как задается вопрос

(ab)Используйте a std::set !

 #include<vector>
#include<set>
#include<functional>
#include<iterator>

class Solution {
public:
    int thirdMax(std::vector<int> constamp; nums) {
        if (nums.size() == 0) return -42; // I like this one.
        std::set<int, std::greater<int>> s(cbegin(nums), cend(nums));
        if (s.size() > 2) return *next(cbegin(s),2);
        return *cbegin(s);
    }
};
  

Ответ №5:

Моя идея заключается в использовании флагов существования.

 class Solution {
public:
    int thirdMax(vector<int>amp; nums) 
    {
        int first = INT_MIN;
        int second = INT_MIN;
        int third = INT_MIN;
        bool firstExists = false, secondExists = false, thirdExists = false;
        
        for(int i=0; i<nums.size(); i  )
        {
            if(!firstExists || nums[i] > first)
            {
                third = second;
                second = first;
                first = nums[i];
                firstExists = true;
            }
            else if((!secondExists || nums[i] > second) amp;amp; nums[i] != first)
            {
                third = second;
                second = nums[i];
                secondExists = true;
            }
            else if((!thirdExists || nums[i] > third) amp;amp; nums[i] != first amp;amp; nums[i] != second)
            {
                third = nums[i];
                thirdExists = true;
            }
        }
        
        if(!thirdExists)
            return first;
        else
            return third;
    }
};
  

Ответ №6:

Поскольку вам нужен весь int домен, использование магического числа like INT_MIN не будет работать правильно.

Использование std::optional<int> в качестве типа для first , second , и third является решением здесь.

Соответствующим образом настройте условные обозначения: if (first) вычисляется true тогда и только тогда, когда first имеет явно установленное значение, и используется *first для доступа к значению, если оно имеет явно установленное значение.