复杂度分析(下)

复杂度分析(下)

@(数据结构与算法)

复杂度除了大 O 表示法,还有最好时间复杂度最坏时间复杂度平均时间复杂度均摊时间复杂度

//n 表示数组 array 的长度
int find(int[] array,int n,int x){
	int i = 0;
	int pos = -1;
	for(; i < n; ++i){
		if(array[i] == x){ 
		pos = i;
		break;}
		}
	return pos;
}

这个程序是查找一个无序数组中 x 变量出现的位置,如果没有找到,就返回 -1 ,此时代码的市价复杂度就不为 O(n),因为变量 x 有可能出现在数组中的任何位置,所以不同情况下,这段代码的时间复杂度是不一样的。

最好时间复杂度:在最理想的情况下,执行这段代码的时间复杂度。此代码为 O(1) 。
最坏时间复杂度:在最糟糕的情况下,执行这段代码的时间复杂度。此代码为 O(n) 。
平均时间复杂度:要查找的变量 x ,要么在数组中,要么不在,假设两者概率都为 1/2 。而在数组中 n 个位置上的概率相同,为 1/n ,所以要查找的数据出现在数组中的概率为 1/(2n),此时平均时间复杂度的计算过程为:

即期望值。通过大 O 表示法,克制平均时间复杂度为 O(n)。

通常只有同一块代码在不同的情况下,时间复杂度有量级的差距,才会通过这三种复杂度表示法区分。

均摊时间复杂度

// array 表示一个长度为 n 的数组
// 代码中的 array.length 等于 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;
}

这段代码实现一个往数组中插入数据的功能。当数组满了之后,通过 for 循环将数组遍历求和,并清空数组,将求和之后的 sum 值放到数组第一个位置,再插入新的数据。但是如果数组一开始就有位置,则直接插入。这段代码的最小时间复杂度为 O(1) , 最大时间复杂度为 O(n) ,平均时间复杂度为 O(1)。

insert() 函数,O(1) 时间复杂度的插入和 O(n) 时间复杂度的插入,出现的频率是有规律的,一个 O(n) 插入之后,紧跟着 n-1 个 O(1) 插入。针队这种特殊场景的时间复杂度分析,采用均摊时间复杂度分析。

每一此 O(n) 插入操作,都会跟着 n-1 次 O(1) 的插入操作,所以把耗时最多的那次操作均摊到接下来的 n-1 次操作行,这一组连续的均摊时间复杂度就是 O(1)。


参考自:极客时间《数据结构与算法之美 》专栏

posted @ 2018-09-28 16:54  我不  阅读(182)  评论(0编辑  收藏  举报