我在做一个问题,其中一部分需要我反复查找向量中的最小元素,直到它们都为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 limits
或{{ 1}}或lower_bound
还是其他?
edit:刚意识到问题本质上是计数排序,或者只是计数排序,或者可能是对其的一些细微修改,问题更多是关于库函数而不是问题,所以不要太在意本文!
答案 0 :(得分:3)
这是要通过 reduce 操作解决的问题,顺便说一下,该操作也可以很好地并行化。
通常,您可以将std::reduce
与std::min
耦合。在您的情况下,您需要一个在检查零值之后调用std::min
的函子/ lambda。
在C ++ 20中,您还可以使用view::filter
从考虑中删除零值。
答案 1 :(得分:3)
如果您反复搜索相同的向量,直到它们全部为0
,我建议从零值中过滤向量(取O(N)),然后对其余向量进行排序(取O(NlogN),然后只需从较低端开始的恒定时间内pop()
个元素,这对于大型数组来说将更快。
您可以在第一步中过滤小于或等于K
的值,而不必过滤0
。
答案 2 :(得分: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);
}
}