复杂度讲解

首先先简单说一下数据结构:可以想象一下未来你是一名程序员,当你要做项目时,要对一些数据进行存储,可以用顺序表(通讯录,数组),还有链表,哈希表,二叉树等高级的数据结构,也就是说数据结构就是我们对数据进行处理的方式。那么这里就不得不提一下算法,算法和数据结构二者是相辅相成的。(数据结构是一门单独的学科,程序员也分会数据结构的和不会数据结构的。二者还是有很大的区别的)

    那么算法的效率亦或者是算法的好坏是靠什么衡量的呢?一般是从时间空间这两个角度来衡量的,即时间复杂度(衡量算法的运行速度)和空间复杂度(衡量算法运行时临时占用的空间大小)。随着计算机的存储量的发展,计算机的储存容量已经到达了很高的乘次,所以更关心的是时间复杂度。

一,时间复杂度(初级)

   定义:算法的时间复杂度是一个数学函数,这个数学函数其实是理想出来的,理论上是要靠程序跑起来之后才知道运行时间的,但要是每次想要知道运行时间我们都需要让代码运行的话就太麻烦了,所以就理想化了这样一个数学模型,因为运行时间与运行次数成正比,所以代码的执行次数就可以被认为是时间复杂度。那么好来看这行代码:++count一共执行了几次呢?

public void Func1(int N) {
            int count = 0;
            for (int i = 0; i < N ; ++ i)
            {
                for (int j = 0; j < N ; ++ j)
                {
                    ++count;
                }
            }
            for (int k = 0; k < 2 * N ; k++)
            {
                ++count;
            }
            int M = 10;
             for (int i = 0; i < M; i++) {
                 ++count;
             }
             System.out.println(count);
        }

那么时间复杂度的函数就是:f(N)=N*N+2*N+10。也就是说一共执行了这么多次,

但是我们发现随着N的增大,似乎后面的2*N+10对总次数的影响越来越小,小到几乎可以忽略不计,那么这里我们就可以用大O渐进法,也就是一种估算方法来粗略的计算时间复杂度。

   大O阶方法的规则:

1.用常数1取代运行时间中的所有加法常数。

 void Func2(int N)
        {
            int count = 0;
            for (int k = 0; k < 100; ++ k)
            {
                ++count;
            }
            System.out.println(count);
        }

就例如上面这行代码:执行了100次,但他是一个常数,所以时间复杂度是O(1),O(1)这就表明了该算法只能执行常数次。

2.在修改后的运行次数函数中,只保留最高阶项。

就好比上面写到的那个函数法f(N)=N*N+2*N+10一样,我们只保留最高项那么法f(N)就约等于N*N,那么这个程序的时间复杂度就是O(N*N)。

3.如果最高阶项存在且系数不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

void Func3(int N)
        {
            int count = 0;
            for (int k = 0; k < 2 * N ; ++ k)
            {
                ++count;
            }
            int M = 10;
            for (int i = 0; i < M; i++) {
                ++count;
            }
            System.out.println(count);
        }

那么它的时间复杂度就是O(N)。

若没有任何条件,则时间复杂度为O(M+N),若M远大于(小于)N,则时间复杂度为O(M)(O(N)),若M和N差不多,则时间复杂度为O(N)或O(M)。

当然每个算法在计算时间复杂度的时候,是存在最好,平均和最坏的情况的:

最坏情况:任意输入规模的最大运行次数(次数最多,上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(次数最少,下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
但是在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为 O(N)

常见的时间复杂度量级
常数阶O(1)
对数阶O(logN)(二分查找)
线性阶O(n)
线性对数阶O(nlogN)(递归)

(这里log2N 与 logN 是等价的)
平方阶O(n2)
立方阶O(n3)
K次方阶O(nk)
指数阶(2^n)(斐波那契数列)

越往下复杂度就越高

 

二,空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中 临时占用存储空间大小的量度 。

空间复杂度跟时间复杂度大致类似,也是用 O 渐进表示法。

注意: 函数运行时所需要的栈空间 ( 存储参数、局部变量、一些寄存器信息等 ) 在编译期间已经确定好了,因 此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

用数组实现斐波拉契数列的空间复杂度:O(N).

用三个变量来回计算斐波拉契数列的空间复杂度是:O(N).

用递归实现的斐波拉契数的空间复杂度:O(N).

空间复杂度基本上是O(1)或者O(N),其它的空间复杂度不常见。假设开一个N*N的数组,那么它的空间复杂度是O(N^2)。结构体不讨论结构体个数,只看整体。不看具体,只看量级。

OK啦今天的分享就到处结束,感谢各位的观看,蟹蟹!!!

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值