c ++ vector的最小值大于另一个值

时间:2015-11-27 10:55:14

标签: c++ vector max min

我有vectordouble个。我希望找到两个:

  • 向量中的最小值大于(或等于)值x
  • 向量中小于(或等于)值x的最大值。

E.g。如果我有一个向量:

std::vector<double> vec = {0, 1.0, 3.0, 4.0, 5.0};

和值

x = 2.6;

我希望找到1.03.0

最有效的方法是什么?

我有类似的东西:

double x1, x2; // But these need to be initialised!!!
double x = 2.6;
for (i = 0; i < vec.size(); ++i)
{
  if (vec[i] >= x && vec[i] < x2)
       x2 = vec[i];
  if (vec[i] <= x && vec[i] > x1)
       x1 = vec[i];
}

但是我如何初始化x1和x2?我可以使x2成为矢量的最大值而x1是最小值,但这需要初始通过数据。有没有办法更有效地做到这一点?

编辑:

我认为我可以/不能对数据做出一些假设:

  • 没有否定(即最小可能的数字为0
  • 不一定排序。

7 个答案:

答案 0 :(得分:3)

您可以使用std::lower_bound

#include <iterator>
#include <algorithm>

template<class ForwardIt, class T>
std::pair<ForwardIt, ForwardIt> hilo(ForwardIt first, ForwardIt last, T const &value)
{
    if (first != last)
    {
        auto lb = std::lower_bound(first, last, value);
        auto prelbd = std::distance(first, lb) - 1;
        if (lb == last) return{ std::next(first, prelbd), last };
        if (!(value < *lb)) return{ lb, lb };
        if (lb == first)  return{ last, first };
        return{ std::next(first, prelbd), lb };
    }
    return{ last, last };
}

可以使用:

std::vector<double> vec = { -1.0, -1.0, 0.0, 1.0, 3.0, 3.0, 3.0, 3.0, 4.0, 5.0, 5.0 };
// if not ordered
//std::sort(vec.begin(), vec.end());
double x = 5.0;
auto b = hilo(vec.begin(), vec.end(), x);
if (b.first != vec.end())
{
  std::cout << "First index: " << std::distance(vec.begin(), b.first) 
    << "(value " << *b.first << ")\n";
}
if (b.second != vec.end())
{
  std::cout << "Second index: " << std::distance(vec.begin(), b.second) 
    << "(value " << *b.second << ")\n";
}

答案 1 :(得分:2)

如果你想避免在整个向量中多加一遍,你总是可以为你正在使用的类型选择最大可能值(在这种情况下,为double)。 STL为您提供了一种方法,请参阅例如这里:

http://www.cplusplus.com/reference/limits/numeric_limits/

对于您的情况,请尝试以下方式:

#include <limits>       // std::numeric_limits
.
.
.
double x1 = std::numeric_limits<double>::max();
double x2 = std::numeric_limits<double>::min();
.
.
.
// rest of your code

答案 2 :(得分:2)

使用迭代器:

First()

答案 3 :(得分:1)

要将x1x2初始化为向量的最小值和最大值,我想您除了通过它之前别无选择,只能通过它,除非您先调用向量std::sort ,并按升序或降序排序,然后根据您的顺序选择列表的头部/尾部,以初始化两个值。

您还可以使用std::min_element从容器中获取最小值,或使用std::max_element来查找容器中的最大元素。

答案 4 :(得分:1)

无需通过向量来获取向量中的最小值和最大值,因为这些值仍然不能保证小于或大于x(考虑向量{{1对于[1 2 3 4] - 你可以初始化x = 5但是在循环之后你会错误地认为它是最小值x1 = 4。)

您似乎需要将>= 5x1初始化为明确标记您是否找到最小值或最大值的值,其中明确表示您不能将它们误认为实际值在向量中。

Yannis Douros给出的一个建议是使用x2std::numeric_limits<double>::min()。 或者你可以选择

std::numeric_limits<double>::max()

在循环过程中,x1 = x - 1; x2 = x + 1; 将被第一个大于x1的值覆盖,因此在循环之后,您需要做的就是检查是否x知道您是否找到了至少。如果有,则其值为x1 >= x

同样,如果x1应为x2,那么小于<= x的最大值为x,另一方面x2x2 > x仍为x2)且您未找到最大值。

答案 5 :(得分:0)

您可以使用以下方法

#include <iostream>
#include <vector>
#include <utility>

int main()
{
    std::vector<double> v = { 0, 1.0, 3.0, 4.0, 5.0 };
    double x = 2.6;

    auto minmax = std::make_pair( v.size(), v.size() );

    for ( std::vector<double>::size_type i = 0; i != v.size(); ++i )
    {
        if ( v[i] <= x && ( minmax.first == v.size() || v[minmax.first] < v[i] ) )
        {
            minmax.first = i;
        }
        else if ( x <= v[i] && ( minmax.second == v.size() || v[i] < v[minmax.second]  ) )
        {
            minmax.second = i;
        }
    }

    if ( minmax.first != v.size() )
    {
        std::cout << "The maximum value less than or equal to " << x
                  << " is " << v[minmax.first] << std::endl;
    }

    if ( minmax.second != v.size() )
    {
        std::cout << "The minimum value greater than or equal to " << x
                  << " is " << v[minmax.second] << std::endl;
    }

    return 0;
}

程序输出

The maximum value less than or equal to 2.6 is 1
The minimum value greater than or equal to 2.6 is 3

如果矢量已排序,那么您可以使用标准算法std::equal_range。 例如

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

int main()
{
    std::vector<double> v = { 0, 1.0, 3.0, 4.0, 5.0 };
    double x = 2.6;

    auto minmax = std::equal_range( v.begin(), v.end(), x );

    if ( minmax.first == minmax.second )
    {
        if ( minmax.first != v.begin() ) std::advance( minmax.first, -1 );
        else minmax.first = v.end();
    }
    else
    {
        std::advance( minmax.second, - 1 ); 
    }


    if ( minmax.first != v.end() )
    {
        std::cout << "The maximum value less than or equal to " << x
                  << " is " << *minmax.first << std::endl;
    }

    if ( minmax.second != v.end() )
    {
        std::cout << "The minimum value greater than or equal to " << x
                  << " is " << *minmax.second << std::endl;
    }

    return 0;
}

程序输出与上面显示的相同。

答案 6 :(得分:0)

可以使用std::partition

完成此操作
std::vector<double> vec = {0, 1.0, 3.0, 4.0, 5.0};
double x = 2.6;
auto middle = std::partition(vec.begin(), vec.end(), 
    [x](const auto& v){return v < x;});
auto max_lt = *std::max_element(vec.begin(), middle); // = 1
auto min_gt = *std::min_element(middle, vec.end()); // = 3