我有vector
个double
个。我希望找到两个:
x
。x
的最大值。E.g。如果我有一个向量:
std::vector<double> vec = {0, 1.0, 3.0, 4.0, 5.0};
和值
x = 2.6;
我希望找到1.0
和3.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
)答案 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)
要将x1
和x2
初始化为向量的最小值和最大值,我想您除了通过它之前别无选择,只能通过它,除非您先调用向量std::sort
,并按升序或降序排序,然后根据您的顺序选择列表的头部/尾部,以初始化两个值。
您还可以使用std::min_element
从容器中获取最小值,或使用std::max_element
来查找容器中的最大元素。
答案 4 :(得分:1)
无需通过向量来获取向量中的最小值和最大值,因为这些值仍然不能保证小于或大于x
(考虑向量{{1对于[1 2 3 4]
- 你可以初始化x = 5
但是在循环之后你会错误地认为它是最小值x1 = 4
。)
您似乎需要将>= 5
和x1
初始化为明确标记您是否找到最小值或最大值的值,其中明确表示您不能将它们误认为实际值在向量中。
Yannis Douros给出的一个建议是使用x2
和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
)且您未找到最大值。
答案 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