在向量中查找大于 0(或通常为 k)的最小元素的最佳方法是什么?

What is the best way to look for the smallest element greater than 0 (or maybe in general k) in a vector?

本文关键字:元素 最佳 是什么 方法 大于 查找 向量      更新时间:2023-10-16

我正在做一个问题,其中一部分要求我反复找到向量中的最小元素,直到它们都是 0。 我用来做的代码是这样的:

loop
int minE = INT_MAX;
for(int z = 0; z < arr.size(); z++) {
if(arr[z] > 0) {
if(arr[z] < minE) minE = arr[z];
}
}
if(minE == INT_MAX) minE = 0; // I had a case to handle them being 0, so I turn them to 0 if all elements are <= 0
// other things (subtract minE from all positive elements and count elements with that turn to 0)
endloop

现在我知道很可能没有办法比线性时间更快,但我只是想知道 STL 中的某些功能是否可以用来实现这种事情,比如min() from limitslower_boundmin_element或其他东西?

编辑:刚刚意识到问题基本上是计数排序,或者只是计数排序,或者可能对它进行一些轻微的修改,问题更多的是关于库函数而不是关于问题,所以不要太介意这篇文章!

这是一个要用reduce操作解决的问题,顺便说一下,它也可以整齐地并行化。

通常,您可以将std::reducestd::min相结合。在您的情况下,您需要一个在检查零值后调用std::min的函子/lambda。

在 C++20 中,您还可以使用view::filter从考虑范围中删除零值。

如果你反复搜索同一个向量,直到它们都0,我建议从零值过滤向量(取 O(N((,然后对其余部分进行排序(取 O(NlogN(,然后从低端在常量时间内pop()元素——这对于大型数组来说会快得多。

您可以在第一步中筛选小于或大于K的值,不一定0

如果可以修改向量中元素的顺序,但不想修改单个值,则可以使用 STL 堆算法。

首先在 O(n( 时间内将非零元素划分到前面,将零元素分区到后面。 然后对非零值执行make_heap操作,这将需要O(numOfNonZeroElements),然后在此范围内重复执行pop_heap(需要O(log(numOfNonZeroElements))时间(,这会将前面的元素放在非零范围的后面,然后将非零范围减少 1。整体复杂性O(n) + O(numOfNonZeroElements*log(numOfNonZeroElements))

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
ostream& operator<< (ostream& out, const vector<int>& V)
{
for (int e : V)
out << e << ' ';
return out;
}
int main()
{
int n;
cin >> n;
vector<int> A(n);
for (int& e : A)
cin >> e;
partition(A.begin(), A.end(), [](int e) { return e > 0; });
cout << A << endl;
vector<int>::iterator begin, end;
begin = A.begin();
for (end = A.begin(); end < A.end() && *end > 0; end = next(end));
make_heap(begin, end, greater<int>());
while (begin < end && A.front() > 0)
{
cout << A.front() << endl; // perform operation on A.front() here
pop_heap(begin, end, greater<int>());
cout << A << endl;
end = prev(end);
}
}