时空复杂度那些事儿(一)

时间复杂度

这段时间准备复习考研,发现时间复杂度一直没整明白,昨晚上听了节王道的网课感觉比之前更清晰一些了,所以把它写下来

频度:一个语句的频度是指该语句被重复执行的次数。
算法问题的规模:n

假设每个语句的执行一次的时间都是1ms,那么以下语句的时间开销是多少呢?1
当n=3000时

  • int i=1 执行了1次
  • while(i<=n) 执行了3001次
  • i++ 执行了3000次
  • printf(“I Love You %d \n”,i); 执行了3000次
  • printf(“I Love You More Than %d\n”,n); 执行了1次

执行的时间= (1+3001+3000+3000+1)*1ms

.

  • 那么问题在于,用算法写成程序后,程序运行的时间来估量算法的优秀程度是否合理?
    答案显然是不合理, 如果同一个算法用C语言实现,和用java实现,低级语言的执行效率会更高,用的时间会更短,而它们本身的算法并无差异。 所以用程序跑的时间来衡量算法时间复杂度是扯淡的

  • 因此在计算时间复杂度的时候,把时间单位毫秒直接省略。只看每条语句执行的次数。每条语句执行的次数之和作为时间复杂度。

然后我们不难发现,上述执行时间(1+3001+3000+3000+1),可以用问题规模n代入
得到 :
算法时间复杂度= 3n+3
因此时间复杂度是关于n的函数记作T(n)

这时会出现两个问题:

  1. 如果代码有几千行需不需要一行一行数?
  2. 如果T(n)=n^3+ n^4 +nlog2n+…太过复杂的情况,可不可以忽略掉某些部分?

下面来进行两组算法的比较:
n=3000时,
1.T1(n)=3n+3 vs T2(n)=3n
9003 vs 9000
2. T1(n)=n^2+3n+1000 vs T2(n)=n^2
9010000 vs 9000000

不难发现,T1和T2的结果其实差别不大。好比两个舍友你俩都有九百万,他炒股赚了一万,他没有比你有钱多少。因此得出结论:时间复杂度表达式,可以只考虑阶数最高的部分,常数部分和阶数低的部分可以省略
例如(3n+3可以忽略3,n^2+3n+1000可以忽略3n和1000)

系数其实也是可以忽略的 例如3n 和 n ,当n=10,一个10,一个30。同样是生活中,拿三十块的小伙伴和拿十块的小伙伴,拿三十块的就不见得富裕多少。

因此可以如此简化:
T(n)=3n+3 可以看作是 n
T(n)=n^2+3n+1000 可以看作是 n^2
这种简化方法,称为大O表示法,即:
T1(n)=O(n)
T2(n)=O(n^2)

此时还有第二个问题,如果代码有几千行需不需要一行一行数?
根据上述的原则,常数是可以被忽略的,因此按顺序执行的代码是可以忽略不记的,只需要关注最深层次内的循环,其中的一条语句的执行次数即可。


关于最深层次循环,其实这里是存在有一个坑的,什么是最深层次的循环? 可以通过下面这个例子学习,并且引出时间复杂度的两条规则
在这里插入图片描述
解析步骤:

  1. 正常执行语句忽略不计
  2. 选择外层循环的一条执行语句,i++ 次数为n
  3. 内层循环的语句 printf(“I am Iron Man\n”) ,次数为n^2
    结果:T(n)=O(n)+O(n^2)
    大O表示法的加法准则,选择其中比较高阶的一项作为结果所以
    T(n)=O(n^2)

因此可以得到结论,时间复杂度只需要关心最内层的循环,选择其中一条语句的执行次数即可。忽略常数和系数,只关注数量级。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值