在解决问题时,我遇到了这样一种情况:我必须从给定的正数数组中找到三个项目组合的第一个k产品,这样产品应该是最小的。
给定数组A
,大小为n
,找到具有最小值的三个不同数组项的第k
个产品。让我们称之为MP
MP[i] = A[j]* A[l]*A[m]
其中i<K, j!=l!=m
和k<n
我在那个时间点尝试过的是获取所有可能的产品,然后对它们进行排序以获得第一批k产品。但我知道这不是有效的,因为首先是O(N ^ 3)用于找到所有组合产品,然后至少O(NlogN)用于分选N ^ 3组合。所以在我的情况下,数组大小并不大,但我想知道如何更有效地解决相同的问题。
答案 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。