问题描述
public static void main(String[] args) {
Scanner sc = new Scanner(system.in);
int n = sc.nextInt();
int m = sc.nextInt();
int result = 0;
for (int i=0; i < n; i++) {
for (int j=m; j > 0; j--)
result += 1;
m -= 1;
}
System.out.println(result);
}
问题是对还是错的问题。该语句是“当n远大于2 m时,以下程序的时间复杂度为O(n m)”。对还是错?
问题中的时间复杂度是指最坏情况下的时间复杂度。这是我到目前为止所做的:
内部循环运行m次,每次m的值减小1。这样,内部循环的迭代总数为:m + m-1 + m-2 + m-3 + .... + 3 + 2 +1。
我们可以认为这是一个算术序列。
然后,内部循环的迭代总数为:m(m +1)/ 2 =(m 2 + m)/ 2。
m达到0后,由于n远远大于2 * m,因此外循环将继续以O(1)时间运行n-m倍。
因此,时间复杂度为:(m 2 + m)/ 2 + n-m = O(m 2 )。
解决方法
不,那是不正确的。首先,这里没有“最坏情况”或“最好情况”,因为步数完全由n
和m
决定。
正如您所说,问题是是/否。因此,简单地计算时间复杂度并不是解决此问题的正确方法(顺便说一句,结果不是 O(m^2)
-您不能只丢弃n
!)。
您的推理直到最后一步都是正确的。如您正确计算的那样,步数为(m^2 - m)/2 + n
(简化后)。问题是:在(m^2 - m)/2 + n
的假设下,O(mn)
是集合n >> 2m
的成员吗?
为简单起见,忽略常量,让我们将假设记为不等式:
(m^2 - m)/2 + n < nm (eventually,as n,m grow)
现在两边除以nm
会产生相等的不等式
(m - 1)/(2n) + 1/m < 1
根据这个假设,第一项消失了,所以我们剩下1/m < 1
,这显然是正确的,随着m
的增长。因此,假设是正确的,而答案是肯定的。