用最少的产品找到三个项目的K组合

时间:2016-09-28 04:54:25

标签: arrays algorithm math combinations

在解决问题时,我遇到了这样一种情况:我必须从给定的正数数组中找到三个项目组合的第一个k产品,这样产品应该是最小的。 给定数组A,大小为n,找到具有最小值的三个不同数组项的第k个产品。让我们称之为MP

MP[i] = A[j]* A[l]*A[m] 

其中i<K, j!=l!=mk<n

我在那个时间点尝试过的是获取所有可能的产品,然后对它们进行排序以获得第一批k产品。但我知道这不是有效的,因为首先是O(N ^ 3)用于找到所有组合产品,然后至少O(NlogN)用于分选N ^ 3组合。所以在我的情况下,数组大小并不大,但我想知道如何更有效地解决相同的问题。

1 个答案:

答案 0 :(得分:2)

其他解决方案的问题是他们的贪婪选择是非最佳的。

基于优先级队列的简单解决方案将为此问题提供最佳解决方案。 min_product 是提供所需数组的函数,地图用于跟踪已见过的元组。我使用了一个简单的stl优先级队列。

//// Asume the vector a(size>=3) is sorted    
std::vector<int> a;
struct triplet{
    int i,j,k;
};

long long value(triplet& p1){
    return (long long)a[p1.i]*(long long)a[p1.j]*a[p1.k];
}

struct CompareTriplet {
    bool operator()(triplet const & p1, triplet const & p2) {
        return value(p1) > value(p2);
    }
};

void push_heap(std::priority_queue<triplet, std::vector<triplet> pq, CompareTriplet>& pq,triplet &t,std::vector<triplet>& m;){
    if (m.find(t)!=m.end()){
        m[t]=1;
        pq.push(t);
    }
}

std::vector<long long> min_product(int k){

    sort(a.begin(), a.end()); // sort if not sorted.
    int n=a.size();

    std::unodered_map<triplet,bool> m;
    std::vector<long long> MP(k);

    std::priority_queue<triplet, std::vector<triplet>, CompareTriplet> pq;

    push_heap(pq,triplet{0,1,2},m);

    for(int i=0; !pq.empty() and i<k;i++){
        auto tp = pq.top(); pq.pop();
        MP[i]=value(tp);

        if (tp.i+1<tp.j){
            push_heap(pq,triplet{tp.i+1,tp.j,tp.k},m);
        }
        if (tp.j+1<tp.k){
            push_heap(pq,triplet{tp.i,tp.j+1,tp.k},m);
        }
        if (tp.k+1<n){
            push_heap(pq,triplet{tp.i,tp.j,tp.k+1},m);
        }
    }
    return MP
}

复杂性

如果数组没有排序,那么将其排序是这里的瓶颈。其实在任何时候,我们都需要顶级i(

对于已排序的给定数组。

由于堆中最多可以有2 * k个元素,并且为获取MP的每个元素而完成O(k)个操作(堆和映射)。因此,运行时间复杂度为 O(k * log(k))

是的,它独立于n。