如果n
给出数字,我如何找到可能的三角形总数?有没有什么方法能在不到一定的O(n^3)
时间内完成这项工作?
我正在考虑a+b>c
,b+c>a
以及a+c>b
成为三角形的条件.
假设在给定的n中没有相等的数字,并且允许多次使用一个数字.例如,我们给出了数字{1,2,3},因此我们可以创建7个三角形:
1 1 1
1 2 2
1 3 3
2 2 2
2 2 3
2 3 3
3 3 3
如果这些假设中的任何一个不成立,则很容易修改算法.
这里我提出了在最坏的情况下需要O(n ^ 2)时间的算法:
排序数字(升序).我们将取三元组ai <= aj <= ak,使得i <= j <= k.
对于每个i,j,您需要找到满足ak <= ai + aj的最大k.然后,所有的三元组(AI,AJ,人).J <= 1 <= k是三角形(因为AK> = AJ> =人工智能我们只能违反AK
考虑两对(i,j1)和(i,j2)j1 <= j2.很容易看出k2(在步骤2中找到(i,j2))> = k1(找到(i,j1)的一步).这意味着如果你迭代j,你只需要检查从前一个k开始的数字.因此,它为每个特定的i 提供O(n)时间复杂度,这意味着整个算法的O(n ^ 2).
C++源代码:
int Solve(int* a, int n) { int answer = 0; std::sort(a, a + n); for (int i = 0; i < n; ++i) { int k = i; for (int j = i; j < n; ++j) { while (n > k && a[i] + a[j] > a[k]) ++k; answer += k - j; } } return answer; }
downvoters的更新:
这肯定是O(n ^ 2)!请仔细阅读Thomas H. Cormen关于摊销分析(第二版中的17.2)的章节"算法介绍". 通过计算嵌套循环来发现复杂性有时是完全错误的. 在这里,我试着尽可能简单地解释它.让我们修复i变量.然后为我我们必须遍历Ĵ从我到Ñ(这意味着为O(n)的操作)和内部while循环迭代ķ从我到Ñ(这也意味着为O(n)操作).注意:我不会从每个j的开头循环开始.我们还需要为每个从0到n的 i做.所以它给出了 n*(O(n)+ O(n))= O(n ^ 2).