n个数字中可能的三角形总数

时间:2011-11-13 08:40:33

标签: c complexity-theory

如果给出n个数字,我如何找到可能的三角形总数?是否有任何方法可以在O(n^3)时间内完成此任务?

我正在考虑成为三角形的a+b>cb+c>aa+c>b条件。

8 个答案:

答案 0 :(得分:51)

假设在给定的n中没有相等的数字,并且允许多次使用一个数字。例如,我们给出了一个数字{1,2,3},因此我们可以创建7个三角形:

  1. 1 1 1
  2. 1 2 2
  3. 1 3 3
  4. 2 2 2
  5. 2 2 3
  6. 2 3 3
  7. 3 3 3
  8. 如果这些假设中的任何一个不成立,则很容易修改算法。

    这里我提出的算法在最坏的情况下花费O(n ^ 2)时间:

    1. 排序数字(升序)。 我们将采用三元组ai&lt; = aj&lt; = ak,使得i <= j <= k。
    2. 对于每个i,j,您需要找到满足ak&lt; = ai + aj的最大k。然后所有三元组(ai,aj,al)j <= l <= k是三角形(因为ak> = aj> = ai我们只能违反ak&lt; a i + aj)。
    3. 考虑两对(i,j1)和(i,j2)j1&lt; = j2。很容易看出k2(在步骤2中找到(i,j2))&gt; = 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
  • 有3个三角形不等式,但只有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

以下是计算三角形的步骤。

  1. 按非递减顺序对数组进行排序。

  2. 分别将第一个和第二个元素的两个指针“i”和“j”初始化,并将三角形的数量初始化为0。

  3. 修复'i'和'j'并找到最右边的索引'k'(或最大'arr [k]'),使'arr [i] + arr [j]&gt; ARR [K]“。可以用'arr [i]'和'arr [j]'作为两边形成的三角形的数量是'k-j'。将'k - j'添加到三角形的数量。

  4. 让我们将'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)

possible answer

虽然我们可以使用二进制搜索来找到'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)个结果。