3sum算法复杂度

时间:2019-02-06 09:56:43

标签: c time-complexity

此代码查找排序数组中是否有三个数字相加得出给定的总和,但是我不确定如何计算其时间复杂度。希望您也提供意见和改进建议。

请注意for循环可以在循环中重置自己。

/* function to find if there are 3 values in the 
sorted array that sum up to a given sum */
int IsSumOf3( int arr[], size_t size, int sum)
{
  int right, left, third;
  right = size-1;
  left = 0;
  while(arr[right] > sum && right > 1)
  {
      --right;
  }
  if(right == 1)
  {
      printf("returned false on right == 1 \n");
      return 0;
  }

  for(third = left+1; third < right; ++third)
  {
      int localSum = arr[right]+ arr[left]+ arr[third];
      if(localSum == sum)
      {
          printf("right |%d|, left |%d|, third |%d|\n",arr[right], arr[left], arr[third]);
          return 1;
      }
      if(localSum > sum)
      {
         --right;
         left = 0;
         third = left;
      }
      if(third+1 == right)
      {
          ++left;
          third = left;
      }
  }
  printf("returned false on exit\n");
  return 0;
}

int main()
{

    int A[] = { 1, 4, 6, 8, 10, 46 };

    IsSumOf3(A,6, 22);
    IsSumOf3(A,6, 11);
    IsSumOf3(A,6, 100);
    IsSumOf3(A,6, 3);

    return 0 ;
}

2 个答案:

答案 0 :(得分:2)

首先,我建议您注释您的代码:这里的人们可以更轻松地为您提供帮助。我还建议您保持简单:第一种方法应该是建立一个2个数字之和的列表,并且其总和低于预期结果,然后尝试为2-values-sum的每个值找到第三个元素列表。

您的算法遍历数组,直到找到有效结果为止。在每次迭代中,如果没有有效的结果,则不再考虑一个值(左或右)。 对于N个元素的数组,最坏情况下的迭代是:

N +(N-1)+(N-2)... + 2 +1 = N * N / 2

最后,复杂度为O(N ^ 2)。

P.S .:请注意,计算left = right = third的情况对复杂性没有影响,因此为了简化计算,我只考虑了这一点。

答案 1 :(得分:0)

您只需遍历数组,就没有嵌套循环的递归调用,所以O(n)

好,现在我阅读了上下文,是的,晚了^^

否则,最坏的情况是值没有排序,因为您必须查看所有值,因此N ^ 3。在这里对数组进行排序。

但是您只使用一个循环,甚至您重新启动它似乎也很神奇……太神奇了,对不起,但是那行不通,例如,您找不到矢量的解决方案{4,6,11,12,12,14,19}和预期的总和36,但是6+11+19==36

我不回答复杂性L.C.可以,但是在算法不起作用时,复杂度是否相关?只要return 0;的复杂度为O(1)^^


P.S。因为我有疑问,我使用了蛮力来检查

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

/* function to find if there are 3 values in the 
sorted array that sum up to a given sum */
int IsSumOf3( int arr[], size_t size, int sum)
{
  int right, left, third;
  right = size-1;
  left = 0;
  while(arr[right] > sum && right > 1)
  {
      --right;
  }
  if(right == 1)
  {
      /*printf("returned false on right == 1 \n");*/
      return 0;
  }

  for(third = left+1; third < right; ++third)
  {
      int localSum = arr[right]+ arr[left]+ arr[third];
      if(localSum == sum)
      {
      /*printf("right |%d|, left |%d|, third |%d|\n",arr[right], arr[left], arr[third]);*/
          return 1;
      }
      if(localSum > sum)
      {
         --right;
         left = 0;
         third = left;
      }
      if(third+1 == right)
      {
          ++left;
          third = left;
      }
  }
  /*printf("returned false on exit\n");*/
  return 0;
}

int brutal(int arr[], size_t size, int sum)
{
  int i,j,k;

  for (i = 0; i != size - 2; ++i) {
    for (j = i+1; j != size -1; ++j) {
      for (k = j+1; k != size; ++k) {
        if ((arr[i] + arr[j] + arr[k]) == sum) {
          /*printf("%d %d %d\n", arr[i], arr[j], arr[k]);*/
          return 1;
        }
      }
    }
  }

  return 0;
}

int main()
{
#define N 6

  int a[N];

  srand(time(NULL));

  for (;;) {
    int i;

    a[0] = rand() % N;

    for (i = 1; i != N; ++i) {
      a[i] = a[i - 1] + (rand() % (N - 1)) + 1; /* suppose must not be equals */
    }

    for (i = a[N-1] + a[N-2] + a[N-3] + 1; i != 0; i -= 1) {
      if (IsSumOf3(a, N, i) != brutal(a, N, i)) {
        int j;

        for (j = 0; j != N; j++)
          printf("%d ", a[j]);
        printf(" / %d\n", i);
        return 0;
      }
    }
  }

  return 0 ;
}