时间复杂度为3和

时间:2016-12-06 09:17:34

标签: algorithm time-complexity

我提供了一段代码,用于解决下面的3和问题。

       int N = 10; 

  for (int i = 0; i < N; i++)// this line gets executed N times
    for (int j = i+1; j < N; j++)// this line gets executed N(N-1) times
      for (int k = j+1; k < N; k++)// this line gets executed  N(N-1)(N-2) times
         if (a[i] + a[j] + a[k] == 0)// How many times does this line gets executed
             cnt++;

我正在使用的教科书说明了这行

if (a[i] + a[j] + a[k] == 0)

执行(N(N-1)(N-2))/ 6次。 但是根据我的分析,语句被执行(N(N-1)(N-2))

为什么有6分区,这是什么证明。

5 个答案:

答案 0 :(得分:1)

我认为通过检查来看这一点可能会说得很清楚。考虑N = 3

的情况
i = 0, 1, 2
j = 1, 2
k = 2

内部if语句只能执行一次,因为最内层循环只允许k = 2,而i = 0j = 1会发生这种情况。所以N(N-1)(N-2)/6 = 3*2*1/6 = 1,这是有道理的。你可以构建更复杂的案例,如果你喜欢那种事情,甚至可以考虑归纳证据。

关于1/6因素的问题,从运行时间的角度来看,这并不重要,因为O(1/6 * N^3)O(N^3)相同。在一般情况下,您向我们展示的代码应该表现为O(N^3)

答案 1 :(得分:1)

让我们简化:

for (int i = 0; i < N; i++)
    for (int j = i+1; j < N; j++)
        ;

第一个循环将执行N次迭代。这很清楚也很明确。

第二个循环将执行:

    {li> N - 1 i == 0 时的迭代次数 {li> N - 2 i == 1 时的迭代次数 {li> N - 3 i == 2 时的迭代次数

等等。您可以使用归纳来证明此循环将执行多少次迭代,然后您可以扩展到3个循环。

提示:总和1 + 2 + ... +(N - 2)+(N - 1)可以证明等于N *(N - 1)/ 2

答案 2 :(得分:1)

你的代码实际上正在进行排列和组合问题:从n个元素中取出三个不同的元素,看它们的和是否为零。那么从n个元素中提取出三种不同元素的组合数量?数学告诉你(N,3)= N *(N-1)(N-2)/ 3!= N (N-1)*(N-2)/ 6

答案 3 :(得分:1)

您可以用另一种方式思考。 您的目标是选择3个数字,且总和为目标(0)。 因此,此问题将转换为置换问题。 所以答案是 结果是 这样您就知道6是怎么来的!

此外,您可以使用O(n ^ 2)解决此问题: 通过使用2个指针,左指针从i + 1开始,右指针从结尾开始。 这是用Java编写的代码:

public int threeSum(int[] nums) { //O(n) Complexity
        int len = nums.length;
        int cnt = 0;
        for (int i = 0; i < len - 2; i++) { //i at most to len - 3 O(n)
            int left = i + 1;
            int right = len - 1;
            while (left < right) { //O(n)
                int sum = nums[i] + nums[left] + nums[right];
                if (sum < 0) left++;
                else if (sum > 0) right--;
                else cnt++;
            }
        }
        return cnt;
    }

enter image description here

答案 4 :(得分:0)

For i = 0, j = 1, k will execute for 2 to N-1 ie if statement will execute for N-2 times.
For i = 0, j = 2, k will execute for 3 to N-1 ie if statement will execute for N-3 times.
:
:
For i = 0, j = N-2, k will execute for N-1 to N-1 ie if statement will execute for 1 times.

That means for i = 0, if statement will execute for :
N-2 + N-3 + .... +1 = (N-2)(N-1)/2.

For i = 1, j = 2, k will execute for 3 to N-1 ie if statement will execute for N-3 times.
For i = 1, j = 3, k will execute for 4 to N-1 ie if statement will execute for N-4 times.
:
:
For i = 1, j = N-2, k will execute for N-1 to N-1 ie if statement will execute for 1 times.

And for i = 1, if statement will execute for :
N-3 + N-4 + .... +1 = (N-3)(N-2)/2.

*
*
For i = N-4, j = N-3, k will execute for N-2 to N-1 ie if statement will execute for 2 times.
For i = N-4, j = N-2, k will execute for N-1 to N-1 ie if statement will execute for 1 times.

And for i = N-4, if statement will execute for :
2+1 = (2)(3)/2.

For i = N-3, j = N-2, k will execute for N-1 to N-1 ie if statement will execute for 1 times.
For i = N-3, j = N-1, k will fail for condition ie if statement will execute for 0 times.
ie (1)(1+1)/2

And for i = N-3, if statement will execute for :
1 = (1)(2)/2.




ie.
i = 0, if statement will execute for (N-2)(N-1)/2
i = 1, if statement will execute for (N-3)(N-2)/2
i = 2, if statement will execute for (N-4)(N-3)/2
.
.
i = N-5, if statement will execute for (3*4)/2
i = N-4, if statement will execute for (2*3)/2
i = N-3, if statement will execute for (1*2)/2

That means total number of times if statement executed is
= (N-2)(N-1)/2 + (N-3)(N-2)/2 + (N-4)(N-3)/2 + ... + (2)(3)/2 + (1)(2)/2
= (1/2)[ 1*2 + 2*3 + 3*4 + ... + (N-2)(N-1)]
= (1/2)[ (N-2)(N-1)(N)/3 ]
= (N)(N+1)(N+2)/6