案例分析1
public int Function(int n, int x)
{
int sum = 0;
for (int i = 1; i <= n; ++i)
{
if (i == x)
break;
sum += i;
}
return sum;
}
1.最坏时间复杂度
当x>n时,代码时间复杂度为O(n)
2.最坏时间复杂度
当x>=1时,代码时间复杂度为O(1)
3.平均时间复杂度
要查找的变量 x 在数组中的位置,有 n+1 种情况:在数组的 0~n-1 位置中和不在数组中。代码执行数累次数为((1+2+3....+n)+n),然后除以所有数量(n+1),就可以得到平均值
以上算法存在问题:未考虑各自情况的发生的概率,x要么在1~n中,不在1~n中,概率都是1/2。因为1~n中各个位置的概率都是一样的为1/n。概率乘法法则,x在1~n中任意位置的概率是1/2n。
那正确的计算方式参考以下推导过程
引入概率之后忽略系数及常量后,以上推导的最终得到加权平均时间复杂度为O(n)。
注意事项:
在大多数情况下,我们并不需要区分最好、最坏、平均情况时间复杂度三种情况。很多时候,我们使用一个复杂度就可以满足需求了。只有同一块代码在不同的情况下,时间复杂度有量级的差距,才会使用这三种复杂度表示法来区分。
案例分析2
// array表示一个长度为n的数组
// 代码中的array.length就等于n
int[] array = new int[n];
int count = 0;
void insert(int val) {
if (count == array.length) {
int sum = 0;
for (int i = 0; i < array.length; ++i) {
sum = sum + array[i];
}
array[0] = sum;
count = 1;
}array[count] = val;
++count;
}
均摊时间复杂度
1.理想情况下count!=array.length,时间复杂度为O(1)。
2.最坏的情况下count==array.length,执行一次循环累加和的操作,时间复杂度为O(n)。
3.平均的情况下,因为限定条件0<=count<=array.length,count在0~array.length中存在的位置可以分为array.length+1种情况(0到n)。
4.当0<=count<array.length时,时间复杂度为O(1)。但是count==array.length的时候是一个例外,它的复杂度是O(n)。而且这n+1种情况发生的概率都是一样的,为1/(n+1)。所以根据加权平均的计算方法,
引入概率之后忽略系数及常量后,以上推导的最终得到均摊时间复杂度为O(1)。
总结:均摊时间复杂度就是一种特殊的平均时间复杂度。当我们在分析时间复杂度是O(1)还是O(n)最简单有效的方法就是凭感觉,如果出现O(1)的次数远大于出现O(n)出现的次数,那么平均平摊时间复杂度就是O(1)。