Arrays 求三项最小乘积的K组合

Arrays 求三项最小乘积的K组合,arrays,algorithm,math,combinations,Arrays,Algorithm,Math,Combinations,在解决一个问题时,我遇到了一种情况,我必须从给定的正数数组中找到三项组合的前k个乘积,这样乘积应该是最小的。 给定数组A,大小为n,有效地找到三个不同数组项的最小值的fistk乘积。让我们把它称为MP MP[i] = A[j]* A[l]*A[m] 其中,i其他解决方案的问题是,他们的贪婪选择是非最优的 基于优先级队列的简单解决方案将为该问题提供最佳解决方案。min_product是提供所需数组的函数,映射用于跟踪已看到的元组。我使用了一个简单的stl优先级队列 //// Asume the

在解决一个问题时,我遇到了一种情况,我必须从给定的正数数组中找到三项组合的前k个乘积,这样乘积应该是最小的。 给定数组
A
,大小为
n
,有效地找到三个不同数组项的最小值的fist
k
乘积。让我们把它称为MP

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

其中,
i其他解决方案的问题是,他们的贪婪选择是非最优的

基于优先级队列的简单解决方案将为该问题提供最佳解决方案。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
}
///a对向量a(大小>=3)进行排序
std::载体a;
结构三联体{
int i,j,k;
};
长-长值(三元组和p1){
返回(长-长)a[p1.i]*(长-长)a[p1.j]*a[p1.k];
}
结构比较程序{
布尔运算符()(三重态常量和p1,三重态常量和p2){
返回值(p1)>值(p2);
}
};
无效推送堆(标准::优先级队列&pq,三元组&t,标准::向量&m;){
如果(m.find(t)!=m.end()){
m[t]=1;
质量推力(t);
}
}
标准::向量最小乘积(int k){
排序(a.begin(),a.end());//如果未排序,则进行排序。
int n=a.size();
std::未排序的地图m;
std::载体MP(k);
std::优先级队列pq;
push_堆(pq,三重态{0,1,2},m);

对于(int i=0;!pq.empty()而且我能不能让数组包含负数??数组只包含正数。这是我在回答中建议的算法的一个变体,因为它不需要贪婪的选择。不幸的是,它假设
a
被排序,这不是问题中的要求。排序增加了
O(n log(n))
复杂性,当
A
未排序时远远不是最佳的。解决方案不需要排序
A
(参见我的答案).@NicolaiEhemann,在我的算法中,一开始我实际上不需要对a的元素进行排序。我将从数组中创建另一个堆,然后删除min,并在实际需要时使用它[ith remove_top将在k==I时调用]。这样,我的复杂度仍然是k的函数。我将为此更新代码。好吧,如果之前没有对输入数组进行排序,那么您肯定至少必须查看a的每个元素才能找到最小的元素,因此复杂度必须是
n
的函数。如果之前对a进行了排序,那么复杂度仅取决于
k
我的算法比你的算法差。哦,我得到了它的复杂度,在任何情况下都取决于n。结果证明,我的解决方案是完全错误的。如果能用正确的复杂度对你的算法进行更正式的描述就好了。