搜索满足条件的特定int的向量的有效方法?

时间:2017-01-16 12:30:25

标签: c++ algorithm search

我正在尝试编写一个有效的操作来搜索向量,特别是识别三个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
        }
      }
    }
  }
}

显然这是非常低效的,是否有任何已知的方法在单个循环中执行此类操作?或者比三个嵌套循环更有效?

1 个答案:

答案 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。缺点是三元组的处理顺序不同。