为啥我的程序超时?随便谈谈时间复杂度

为啥我的程序超时?随便谈谈时间复杂度
      我读的书很少,所以这篇文章纯粹代表我个人的见解而非官方的定义以及绝对正确的认知。不过我也知道自己读的书很少,所以在需要得到官方定义以及更加准确的认知的话,我会奉上传送门。

    为啥我们的程序会超时,那么显然,如果你的程序的运算的指令太太太太太太多了,计算机不能一下子跑完所有的指令,那么sicily妹子就会强行终止你的程序,返回Time Limit Exceed(超出时间限制)。
    那么如何避免超时呢?避免问题之前首先要认知问题。首先你要对你自己的程序到底会执行多少次运算有一个估计。而时间复杂度就是计量程序运行时间的一个工具。
时间复杂度的wiki解释释:
http://zh.wikipedia.org/wiki/%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6  

     时间复杂度我个人认为其是是对你程序随着输入数据规模增长而运算次数增长的一个判断。他【忽略常数!】。什么叫程序运算次数随着输入数据规模增长呢?看看下面一个例子:
#include <iostream>
using namespace std;
int main{
    int n, m, a;
    cin>>n;
    for (int i=1; i<100; i++) a++;
    for (int i=1; i<=n*n; i++) a++;
    return 0;


    显然的,关于a的运算次数为100+n*m,如果n增大,那么运算次数当然上升,然而你可以发现,增大和100这个常数是无关的,也就是说,随着输入数据增大,他增长的趋势(增长的速率)和那个100无关。此时,时间复杂度应该是O(n^2)
    同理,如果改动一下语句,为:
    for (int k=1; k<10; k++)
        for (int i=1; i<=n; i++) a++; 
    那么时间复杂度仍然为O(n^2),因为双重循环中循环k也是一个常数,无论n怎么变大,他始终和变化的趋势没有关系。

    这里引出一个问题,时间复杂度并不是多少重循环就是n的几次方,而是要代入每重循环具体干了啥。而且时间复杂度一般考虑的是运算上界(也就是说考虑最坏情况)比如给出n个数,查看每个数是否素数,那么时间复杂度是
    O(n根号(a))  a为输入中可能的最大的数,你可以看到这里保证了最坏情况,虽然有的第二重循环没有循环到根号a就跳出了(例如偶数,到了2就跳出了),但是我们在算时间复杂度的时候必须考虑最坏情况。

    而且我个人感觉时间复杂度因为研究的更多是程序运算时间与输入增大时的变化趋势。所以通常会忽略低次数的项。例如你的程序运算次数为 3n^3 + 100000000n^2 那么我们依然会无视掉常数和次数低的项,把时间复杂度视作O(n^3)

    所以我强调,时间复杂度并不是判断一个程序是否一定超时的工具,更多的是让你对自己程序的运算增长有一个感知。哪怕是O(n^10)的一个程序,可能因为他具有一个极小的常数他仍然能够在给定时间内完成解答(虽然这个现实中不太可能出现)。因此判断自己程序是否超时要结合时间复杂度和自己程序的常数去判断。常数是个很神奇的东西,例如一次运算,浮点运算通常比整形运算要慢得多。函数的调用通常也比一个if语句慢。因此,不要执着于去“数”次数,除非你是精通计算机基层以及编程语言本身的大师,否则那纯粹浪费时间。你在做题唯一要做的,【【是不要给予自己程序一个太荒唐的时间复杂度即可了】】。
    (一般而言,比较正常的数据的话,一般都是算完时间复杂度后次数换算关系为1亿次约等于1秒。赛场上是有许多小技巧去优化常数的,我不会告诉你++i比i++要快,但是浸淫于此绝非正道。

最后强烈推荐此文:
http://www.matrix67.com/blog/archives/105
我就是看这个理解时间复杂度的,也强烈推荐这位大神的其他博文,非常有意思。 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在编程中,如果一段代码运行超时,通常意味着其执行效率不高,时间复杂度过高,导致在处理大量数据或长时间运行的情况下性能表现不佳。降低时间复杂度是优化代码的关键,主要可以从以下几个方面入手: 1. **算法选择**:确保使用的算法是最优的,比如对于查找操作,使用哈希表(O(1))通常比线性搜索(O(n))更快。 2. **数据结构**:选择合适的数据结构可以极大地影响代码效率。例如,使用集合(如Set或Map)而不是列表进行成员查找,可以减少搜索时间。 3. **避免冗余计算**:如果存在重复计算,考虑使用缓存或动态规划来存储中间结果,避免重复劳动。 4. **循环优化**:分析循环,看是否可以通过减少循环次数、并行化处理或者改变循环条件来改善。 5. **空间换时间**:有时候牺牲一些内存空间可以换取更快的执行速度,比如使用预排序或者空间效率较低的数据结构。 6. **分治法和递归**:对于大规模问题,将问题分解为小规模子问题可能有助于降低时间复杂度。 7. **外部存储或数据库**:如果数据量非常大且频繁访问,考虑使用外部存储或数据库系统,它们通常提供更高效的查询机制。 如果你能提供具体的代码片段,我可以给出更针对性的建议。现在,请告诉我你遇到的具体问题代码是什么,或者描述一下代码执行的任务和目前的时间复杂度情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值