在向量中寻找大于0的最小元素的最佳方法是什么?

时间:2020-01-13 08:14:02

标签: c++ c++17

我在做一个问题,其中一部分需要我反复查找向量中的最小元素,直到它们都为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:刚意识到问题本质上是计数排序,或者只是计数排序,或者可能是对其的一些细微修改,问题更多是关于库函数而不是问题,所以不要太在意本文!

3 个答案:

答案 0 :(得分:3)

这是要通过 reduce 操作解决的问题,顺便说一下,该操作也可以很好地并行化。

通常,您可以将std::reducestd::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);
    }
}