数据结构与算法-复杂度

490 阅读3分钟

恋上数据结构跟算法学习笔记总结,我是按照视频学习顺序记录的,如有错误,不吝赐教。

一.什么是算法?

  • 算法就是用来解决特定问题的一系列的执行步骤

二.斐波拉契算法

  • 1.什么是斐波拉契算法?
//第n位数据值 = 第n-1位数据值 + 第n-2位数据值
0,1,1,2,3,5,8,13.....
  • 2.有几种方式写呢? 第一种简单方式
-(int )fib:(int) n {

    //排除n=0,1 两种情况

    if (n<=1) {

        return n;
    }

    /** @算法解析=======

         第n位数据值=第n-1位数据值+第n-2位数据值

     */

    return [self fib:n-1]+[self fib:n-2];

}

第二种优化方案

-(int )sum2:(int) n {

    //排除n=01 两种情况

    if (n<=1) {

        return n;

    }

    /* @算法解析=======

        声明两个变量

        first=0; 代表第0位的数据值

        second=1; 代表第1位的数据值

        i < n-1; 代表求第n位数据值的时候,需要循环计算n-1次,下标i=0,所以i<n-1

        sum = first + second; 代表second后面一位等于前两位之和

        first = second; 代表first往后移动一位,移到second位置上

        second = sum; 代表second往后移动一位,移到sum位置上

        return second; 代表返回最后一组循环结束后second移动到的位置

     *
     */

    

    int first = 0;

    int second = 1;

    for (int i = 0; i < n-1; i++) {

        int sum = first+second;

        first = second;

        second = sum;

    }

    return second;

}
  • 3.两种方式有什么不同?
    • 第一种方式适用于n比较小的情况,n一旦稍微比较大时,这个算法很费时间,因为重复调用
    • 第二种方式不用区分n大小,即使n比较大,这个算法也不费时间
    • 两个方法的耗时时间可以通过特定工具监测,在这里我就不测了
  • 斐波拉契算法时间复杂度分析 先看第一种方式的时间复杂度,可以理解为,调了几次sum函数,时间复杂度就是几,用图分析一下调用顺序

第一种方式调用次数.png

通过上图分析,调用次数n = 1+2+4+8 = 2^0 + 2^1 + 2^2 + 2^3 = 2^4 -1 = 2^(n-1) - 1 = 0.5 * 2^n - 1 时间复杂度为:O(2^n)

再来看第二种方式的时间复杂度为:O(n)

根据下图不同时间复杂度的对比,可以看出O(n) < O(2^n)

数据规模较大时间复杂度比较.png

三.如何评价一个算法好坏?

  • 正确性,可读性,健壮性(对不合理输入的反应能力)
  • 时间复杂度(time complexity):估算程序指令的执行次数(执行时间)
  • 空间复杂度(space complexity):估算所需占用的存储空间

四.大O表示法

  • 一般用大O表示法来描述复杂度,它表示的是数据规模n对应的复杂度
  • 使用原则忽略常数,系数,低阶,对数阶一般省略底数
    • 9 = O(1)
    • 2n + 1 = O(n)
    • n^2 + 2n + 1 = O(n^2)
    • 4n^3 + n^2 + 2n + 1 = O(n^3)
    • log2n = O(logn)
    • 2nlog5n = O(nlogn)
  • 常见的复杂度

时间复杂度.png

时间复杂度比较,越往后,说明时间复杂度越高 O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

五.算法的优化方向

  • 用尽量少的存储空间
  • 用尽量少的执行步骤(执行时间)
  • 根据情况,可以考虑空间换时间,时间换空间

六.多个数据模式的情况

看一下下面的算法,时间复杂度由n,k 共同决定

-(void)testn:(int)n k:(int)k {

    for (int i = 0; i<n; i++) {

        NSLog(@"n");

    }

    for (int i = 0; i<k; i++) {

        NSLog(@"k");

    } 

}

所以上述复杂规模的时间复杂度为:O(n+k),当是复杂规模时,要把所有因素都考虑进去。

本篇先记录到次,如有错误,不吝赐教。