如果给出n
个数字,我如何找到可能的三角形总数?是否有任何方法可以在O(n^3)
时间内完成此任务?
我正在考虑成为三角形的a+b>c
,b+c>a
和a+c>b
条件。
答案 0 :(得分:51)
假设在给定的n中没有相等的数字,并且允许多次使用一个数字。例如,我们给出了一个数字{1,2,3},因此我们可以创建7个三角形:
如果这些假设中的任何一个不成立,则很容易修改算法。
这里我提出的算法在最坏的情况下花费O(n ^ 2)时间:
考虑两对(i,j1)和(i,j2)j1< = j2。很容易看出k2(在步骤2中找到(i,j2))> = k1(找到(i,j1)的一个步骤2)。这意味着如果你迭代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 变量。那么对于 i ,我们必须将 j 从 i 迭代到 n (这意味着O(n)操作)并且内部while循环迭代 k 从 i 到 n (它也意味着O(n)操作)。 注意:我不会从头开始为每个 j 启动。我们还需要为每个i从 0 到 n 执行此操作。所以它给我们 n *(O(n)+ O(n))= O(n ^ 2)。
答案 1 :(得分:4)
如果你使用二进制排序,那就是O(n-log(n)),对吗?保持你的二叉树方便,并为每一对(a,b)保持b和c
答案 2 :(得分:4)
O(n^2*logn)
中有一个简单的算法。
(a, b, c)
,其中a <= b <= c
。a + b > c
就足够了(其他则是平凡的)。现在:
O(n * logn)
中的序列进行排序,例如通过merge-sort。(a, b), a <= b
,剩余价值c
必须至少为b
且小于a + b
。[b, a+b)
中的项目数。这可以通过二元搜索a + b(O(logn)
)并计算[b,a+b)
中每个可能性为b-a的项目数来完成。
所有O(n * logn + n^2 * logn)
O(n^2 * logn)
。希望这会有所帮助。
答案 3 :(得分:2)
让a,b和c为三个方面。以下条件必须适用于三角形(两边的和大于第三边)
i) a + b > c
ii) b + c > a
iii) a + c > b
以下是计算三角形的步骤。
按非递减顺序对数组进行排序。
分别将第一个和第二个元素的两个指针“i”和“j”初始化,并将三角形的数量初始化为0。
修复'i'和'j'并找到最右边的索引'k'(或最大'arr [k]'),使'arr [i] + arr [j]&gt; ARR [K]“。可以用'arr [i]'和'arr [j]'作为两边形成的三角形的数量是'k-j'。将'k - j'添加到三角形的数量。
让我们将'arr [i]'视为'a',将'arr [j]'视为b,将'arr [j + 1]'和'arr [k]'之间的所有元素视为'c'。满足上述条件(ii)和(iii)是因为'arr [i]&lt; arr [j]&lt; ARR [K]”。当我们选择'k'
时,我们检查条件(i)4.增加'j'以再次修复第二个元素。
请注意,在第3步中,我们可以使用之前的'k'值。原因很简单,如果我们知道'arr [i] + arr [j-1]'的值大于'arr [k]',那么我们可以说'arr [i] + arr [j]'也将大于'arr [k]',因为数组按递增顺序排序。
5.如果'j'已达到结束,则递增'i'。将'j'初始化为'i + 1',将'k'初始化为'i + 2'并重复步骤3和4.
时间复杂度: O(n ^ 2)。 由于3个嵌套循环,时间复杂度看起来更多。如果我们仔细研究算法,我们观察到k在最外层循环中只被初始化一次。对于最外层循环的每次迭代,最内层循环最多执行O(n)时间,因为k从i + 2开始并且对于j的所有值都向上移动n。因此,时间复杂度为O(n ^ 2)。
答案 4 :(得分:1)
我制定了一个在O(n ^ 2 logn)时间内运行的算法。我认为它是正确的...... 代码是用C ++编写的......
int Search_Closest(A,p,q,n) /*Returns the index of the element closest to n in array
A[p..q]*/
{
if(p<q)
{
int r = (p+q)/2;
if(n==A[r])
return r;
if(p==r)
return r;
if(n<A[r])
Search_Closest(A,p,r,n);
else
Search_Closest(A,r,q,n);
}
else
return p;
}
int no_of_triangles(A,p,q) /*Returns the no of triangles possible in A[p..q]*/
{
int sum = 0;
Quicksort(A,p,q); //Sorts the array A[p..q] in O(nlgn) expected case time
for(int i=p;i<=q;i++)
for(int j =i+1;j<=q;j++)
{
int c = A[i]+A[j];
int k = Search_Closest(A,j,q,c);
/* no of triangles formed with A[i] and A[j] as two sides is (k+1)-2 if A[k] is small or equal to c else its (k+1)-3. As index starts from zero we need to add 1 to the value*/
if(A[k]>c)
sum+=k-2;
else
sum+=k-1;
}
return sum;
}
希望它有所帮助........
答案 5 :(得分:1)
虽然我们可以使用二进制搜索来找到'k'的值,从而提高时间复杂度!
答案 6 :(得分:-1)
N0,N1,N2,...Nn-1
sort
X0,X1,X2,...Xn-1 as X0>=X1>=X2>=...>=Xn-1
choice X0(to Xn-3) and choice form rest two item x1...
choice case of (X0,X1,X2)
check(X0<X1+X2)
OK is find and continue
NG is skip choice rest
答案 7 :(得分:-1)
似乎没有比O(n ^ 3)好的算法。在最坏的情况下,结果集本身具有O(n ^ 3)个元素。
例如,如果给出n个相等的数字,算法必须返回n *(n-1)*(n-2)个结果。