我正在尝试编写一个有效的操作来搜索向量,特别是识别三个int(A1,A2,A3)的存在,其中A1> A2&& A2< A3。
所以给定A {5,3,1,2,3},输出操作:[3,1,2],[3,2,3],[5,1,3],[5, 1,2]
显而易见的方法是使用三个嵌套循环:
int my_function()
{
std::vector<int> A {3,5,3,1,2,3};
for(auto IT1 = A.begin(); IT != A.end(); IT1++)
{
for(auto IT2 = IT1 + 1; IT2 != A.end(); IT2++)
{
for(auto IT3 = IT2 + 1; IT3 != A.end(); IT3++)
{
if(*IT1 > *IT2 && *IT3 > *IT2)
{
//Do stuff
}
}
}
}
}
显然这是非常低效的,是否有任何已知的方法在单个循环中执行此类操作?或者比三个嵌套循环更有效?
答案 0 :(得分:4)
如果你想找到所有这些三元组,那么没有什么是渐近更快的,因为这样的三元组的数量可以达到O(N^3)
。
UP: Hovewer,如果你以某种方式保证没有那么多这样的三元组(假设你有T = o(N^3)
个),你可以编写一个更有效的算法
让迭代遍历数组的所有元素,并尝试将当前元素放在三元组的中间。为此,我们需要维护两组有序的值:当前值左侧的所有值之一,右侧是sencond。这是代码:
// Initialization
std::multiset<int> left; // empty set
std::multiset<int> right(A.begin(), A.end()); // set of all elements in A
// Iterations
for (int x : A) {
right.erase(x);
for (auto l = left.rbegin(); l != left.rend() && *l > x; ++l) {
for (auto r = right.rbegin(); r != right.rend() && *r > x; ++r) {
// Do stuff with triplet *l, x, *r.
}
}
left.insert(x);
}
此类解决方案的复杂性为O(T + NlogN)
,如果O(N^3)
较小,则远小于T
。缺点是三元组的处理顺序不同。