在算法时间复杂度的求解中,关于for循环中 “()” 以内语句执行的频度一直不太明白,究竟是按照判断语句还是按照类似 i++ 的执行语句来,于是通过一些例子来理解一下。
//求两个方阵相加
void matrixadd(int n, int A[MAX][MAX], int B[MAX][MANX], int C[MAX][MAX])
{
int i, j;
for (i = 0; i < n; i++)//变量i从0增加到n,测试i=n时,才会终止,故它的频度是n+1,而它的循环体执行n次
for (j = 0; j < n; j++)//变量j从0增加到n,测试j=n时,才会终止,频度为n+1,且又在语句1的内部,故执行次数n(n+1)
C[i][j] = A[i][j] + B[i][j];//在两层循环的内部,执行次数n²
}
//T(n)=n+1+n(n+1)+n²=O(n²)
//算法空间复杂度 S(n)=O(1)
第一层循环:for (i = 0; i < n; i++) {……}
对于该语句,变量i从0增加到n,测试i=n时,才会终止,故它的频度是n+1,而它的循环体执行n次。
第二层循环:for (j = 0; j < n; j++) {……}
变量j从0增加到n,测试j=n时,才会终止,频度为n+1,且又在语句1的内部,故执行次数n(n+1)。
简化的算法时间复杂度:直接看频度最大的语句,一般为循环最深层的语句。
//简化的算法时间复杂度
void func(int n)
{
int i = 0, s = 0;//设while循环执行次数m,变量i从0递增到m为止,循环结束时,s=m(m+1)/2>=n,s+k=n,解得m,其中k用于用于修正
while (s < n)
{
i++;
s = s + i
}
}
//求含n个整数元素的序列中前i个元素的最大值
int fun(int a[], int n, int i)
{
int j, max = a[0];
for (j = 1; j < i - 1; j++)
{
if (a[j] > max)
max = a[j];
}
return(max);
}
//i的取值范围是 1~n ,共n种情况,每种情况的概率为1/n
//求前i个元素需要比较(i-1)-1+1=i-1 次
//求和再乘以概率,T(n)=(n-1)/2=O(n) 平均算法时间度
//最好时间复杂度O(1),此时i=1 最坏时间复杂度O(n),此时i=n
本题涉及到平均算法时间复杂度,最好和最坏算法时间复杂度。
递归算法时间复杂度分析:
//递归算法时间复杂度分析
//调用该算法语句为fun(a,n,0),求其算法时间度
void fun(int a[], int n, in k)//设执行时间为 T(n,k)
{
int i;
if (k == n - 1)
{
for (i = 0; i < n; i++)
printf("%d\n", a[i]);//该语句执行次数为n
}
else
{
for (i = k; i < n; i++)
a[i] = a[i] + i * i;//该语句执行次数为 n-k
fun(a, n, k + 1);//执行一次,执行时间为 T(n,k+1)
}
}
//当k=n-1时,T(n,k)=n
//当k!=n-1时,T(n,k)=n-k+ T(n,k+1)
//T(n,0)= n+T(n,1) = n+(n-1)+T(n,2) = …… = n+(n-1)+(n-2)+……+2 +T(n,n-1) = n+(n-1)+(n-2)+……+2 +n = (n+2)(n-1)/2 +n = O(n²)