数据结构——简单的时间复杂度分析

我们常见的时间复杂度表示:O(1), O(n), O(lgn), O(nlog2n), O(n2)。这里的O是渐进时间复杂度,表示n趋于无穷大时,运行时间和输入数据之间的关系。下面用一个例子来简单的分析时间复杂度。

	public int sum(int[] nums){
		int sum = 0;				//(1)
		for(int num : nums)			//(2)
			sum+=num;				//(3)
		return sum;					//(4)
	}

在这个例子里nums中的元素个数就是n,这个方法消耗时间T与n成线性关系:T = c1*n+c2。忽略常数c1,c2。即我们的时间复杂度为O(n),n趋于无穷大时,低阶项忽略。

例一
分析上一篇动态数组的添加操作:
1.addLast(e) 尾插 从数组元素尾部直接插入,不用挪动数组,所以时间复杂度是O(1)
2.addFirst(e) 头插 从数组头部插入元素,需要挪动所有(n)元素,所以时间复杂度是O(n)
3.add(index,e) 在index插入元素 需要挪动n-index个元素,这里的index可以等于从0-size任何一个数,等于每个数的概率相等,可以算出平均时间复杂度的期望。平均而言,时间为n/2,所以时间复杂度为O(n/2)=>O(n)

在算法复杂度的计算上通常考虑0最坏情况

另外在添加时,会有可能resize,所以对于动态数组的添加操作的时间复杂度是O(n)

均摊复杂度

如果一个相对比较耗时的操作,不会每次都触发,那么这个操作的时间可以分摊到其他操作中。

  • 例二
    分析上述中addLast(e)的均摊复杂度

复杂度震荡

对于上一篇动态数组的添加(addLast)和删除(removeLast)操作可以分析出它们的均摊时间复杂度都是O(1),但是对于下面的场景:

当前数组的size = data.length,如果我们不停的重复
addLast(e),removeLast(e),addLast(e),removeLast(e)……

那么会不停的触发resize,这样每一次的复杂度都是O(n)。这就是复杂度的震荡。

这里的原因是由于我们的removeLast中对于resize过于eager了,每次size等于一半时就立马resize。
解决办法:我们可以lazy一点,把1/2变成3/4或其他。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值