我提供了一段代码,用于解决下面的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分区,这是什么证明。
答案 0 :(得分:1)
我认为通过检查来看这一点可能会说得很清楚。考虑N = 3
:
i = 0, 1, 2
j = 1, 2
k = 2
内部if
语句只能执行一次,因为最内层循环只允许k = 2
,而i = 0
和j = 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
次迭代。这很清楚也很明确。
第二个循环将执行:
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;
}
答案 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