繁体   English   中英

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

[英]c++ minimum value of vector greater than another value

我有一个double s vector 我希望找到两个:

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

例如,如果我有一个向量:

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
  • 它不一定排序。

你可以使用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";
}

如果你想避免在整个向量中额外传递,你总是可以为你正在使用的类型获取最大可能值(在这种情况下,为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

使用迭代器:

auto maxBelowX = vec.end();
for (auto i = vec.begin(); i != vec.end(); ++i)
{
    if (*i <= x && (i == vec.end() || *i > maxBelowX)) {
        maxBelowX = i;
    }
}

if (maxBelowX == vec.end()) {
    std::cout << "There was no element <= x";
}

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

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

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

看起来您需要的是将x1x2初始化为明确标记您是否找到最小值或最大值的值,其中明确表示您不能将它们误认为向量中的实际值。

Yannis Douros给出的一个建议是使用std::numeric_limits<double>::min()std::numeric_limits<double>::max() 或者你可以去

x1 = x - 1;
x2 = x + 1;

在循环期间, x1将被第一个大于x值覆盖,因此在循环之后,您需要做的就是检查x1 >= x是否知道您是否找到了最小值。 如果有,则其值为x1

类似地,如果x2应该<= x ,那么小于x最大值是x2 ,如果另一方面x2 > x x2仍然是x + 1 )并且你没有找到最大值。

您可以使用以下方法

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

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

这可以使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM