数据结构与算法系列二(复杂度分析)

1.引子

1.1.为什么要学习数据结构与算法?

有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀!

有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗?

于是问题来了:为什么还要学习数据结构与算法呢?

#理由一:
    面试的时候,千万不要被数据结构与算法拖了后腿
#理由二:
    你真的愿意做一辈子CRUD Boy吗
#理由三:
    不想写出开源框架,中间件的工程师,不是好厨子

1.2.如何系统化学习数据结构与算法?

我想好了,还是需要学习数据结构与算法。但是我有两个困惑:

1.如何着手学习呢?

2.有哪些内容要学习呢?

学习方法推荐:

#学习方法
1.从基础开始,系统化学习
2.多动手,每一种数据结构与算法,都自己用代码实现出来
3.思路更重要:理解实现思想,不要背代码
4.与日常开发结合,对应应用场景

学习内容推荐:

数据结构与算法内容比较多,我们本着实用原则,学习经典的、常用的数据结构、与常用算法

#学习内容:
1.数据结构的定义
2.算法的定义
3.复杂度分析
4.常用数据结构
    数组、链表、栈、队列
    散列表、二叉树、堆
    跳表、图
5.常用算法
    递归、排序、二分查找
    搜索、哈希、贪心、分治
    动态规划、字符串匹配

2.考考你

在开篇中提到了复杂度分析,与大O表示法的概念。具体要如何进行复杂度分析,以及大O表示法的公式推导,我们在这一篇详细来看。

#考考你:
1.你知道大O表示法,公式是如何来的吗?
2.你知道时间复杂度分析的常用原则吗?
3.你知道常见复杂度的度量级吗?

3.案例

3.1.大O表示法公式推导

3.1.1.案例代码

我们根据以下案例代码推导大O表示法的公式。代码很简单,有没有?

// 传入参数n,求解1..n的累加和
public int sum(int n){
    int sum = 0;
    for(int i = 1; i <= n; i++){
        sum += i;
    }

    return sum;
}

3.1.2.推导过程

简述:

1.对于程序代码中的每一行代码,从cpu的角度来看,执行的时候都有:读数据->运算->写数据过程

2.我们假定每一行代码的执行时间都相同,都是一个单位时间:unit_time

3.那么sum方法中,代码执行的总时间是多少呢

1 public int sum(int n){
2    int sum = 0;// 第二行代码执行,需要1 个unit_time
3    for(int i = 1; i <= n; i++){// 第三行代码执行,需要n 个unit_time
4        sum += i;// 第四行代码执行,需要n 个unit_time
5    }
6    return sum;// 第五行、第六行代码暂时忽略,不影响
7 }

4.根据3推导,sum方法的总执行时间是:

T(n)=(n + n + 1) * unit_time = (2n +1) * unit_time=O(f(n))

5.结论:所有代码的执行时间T(n),与每行代码的执行次数成正比

6.提取出公式即:T(n) = O(f(n))

#公式解读:
 T(n):代表代码执行时间
 n:代表数据规模
 f(n):代表每行代码执行的次数总和
 O:表示代码执行时间T(n),与代码执行次数f(n)成正比

7.这就是大O表示法的公式来源,表示代码的执行时间T(n),与代码的执行次数f(n)成正比

8.进一步理解:

1.大O表示法:时间复杂度,表示数据规模n的增长,与算法执行时间的增长趋势
2.大O表示法:空间复杂度,表示数据规模n的增长,与算法存储空间的增长趋势

3.1.3.约定

大O表示的公式,以及含义我们已经推导出来了。它表示的是数据规模n的增长,与算法执行时间,或者存储空间的增长趋势。这里需要关注两个字:趋势

根据常理我们知道,常量系数低阶不会影响趋势,因此在实际复杂度分析中,往往忽略常量、系数、低阶。

那么上面案例的时间复杂度大O表示法公式,省略系数、常量:

可以从:T(n) = O(f(n)) = O(2n+1)

简化成:T(n) = O(n)

3.2.时间复杂度案例

在复杂度分析中,有时间复杂度分析和空间复杂度分析。它们是从两个维度来衡量算法的优劣。实际分析方式类似,我们以时间复杂度分析为例。

时间复杂度分析,有几个基本的原则,你都知道吗?

#时间复杂度分析基本原则
1.只关注循环次数最多的代码
2.加法法则:总复杂度等于量级最大的那段代码的复杂度
3.乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

3.2.1.只关注循环次数最多的代码

案例代码:

1 public int sum(int n){
2    int sum = 0;// 第二行代码执行,需要1 个unit_time
3    for(int i = 1; i <= n; i++){// 第三行代码执行,需要n 个unit_time
4        sum += i;// 第四行代码执行,需要n 个unit_time
5    }
6    return sum;// 第五行、第六行代码暂时忽略,不影响
7 }

复杂度分析:

1.这里的原则:只关注循环次数最多的代码

2.第二行代码执行,需要1 个unit_time

3.第三行代码执行,需要n 个unit_time

4.第四行代码执行,需要n 个unit_time

5.第五行、第六行代码暂时忽略,不影响

6.通过以上分析,第三行、第四行代码循环执行次数最多:n。因此时间复杂度为:O(n)

3.2.2.加法法则

简述:

加法法则:总复杂度等于量级最大的那段代码的复杂度

案例代码:

public int sum(int n){

    // 第一段代码
    int sum_1 = 0;
    for(int i=1; i< 100; i++){
        sum_1 += i;
    }

    // 第二段代码
    int sum_2 = 0;
    for(int j = 1; j <= n; j++){
        sum_2 += j;
    }

    // 第三段代码
    int sum_3 = 0;
    for(int k = 1; k <= n;k++){
        for(int h = 1; h <= n; h++){
            sum_3 += k * h
        }
    }

    return sum_1 + sum_2 + sum_3;

}

复杂度分析:

1.在sum方法中有两段代码

2.第一段代码,复杂度是:O(100)

3.第二段代码,复杂度是:O(n)

4.第三段代码,复杂度是:O(n^2)

5.总复杂度是:O(100) + O(n) +O(n^2)

6.根据加法法则,最终复杂度是:O(n^2)

3.2.3.乘法法则

简述:

乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

案例代码:

public int sum(int n){
     int sum_1 = 0;
    for(int i=1; i< n; i++){// 第一层循环
        sum_1 += multi(i) ;// multi方法中,有第二层循环
    }
}

public int multi(int n){
    int multi_1 = 0;
    for(int i = 1; i<= n; i++){// 第二层循环
        multi_1 *= i;
    }

    return multi_1;
}

复杂度分析:

1.在sum方法中,有第一层循环:for(int i=1; i< n; i++){

2.在sum方法中,调用multi方法

3.在multi方法中,有第二层循环:for(int i = 1; i<= n; i++){

4.根据乘法法则,总时间复杂度等于,第一层循环,乘以第二层循环

5.因此总时间复杂度是:O(n*n) = O(n^2)

4.讨论分享

#考考你答案:
1.你知道大O表示法,公式是如何来的吗?
 1.1.参考【3.1.大O表示法公式推导】

2.你知道时间复杂度分析的常用原则吗?
 2.1.只关注循环次数最多的代码
 2.2.加法法则:总复杂度等于量级最大的那段代码的复杂度
 2.3.乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

3.你知道常见复杂度的度量级吗?
 3.1.常数阶:O(1)
 2.2.对数阶:O(logn)
 2.3.线性阶:O(n)
 2.4.线性对数阶:O(nlogn)
 2.5.平方阶:O(n^2)
 2.6.立方阶:O(n^3)

原文地址:https://www.cnblogs.com/itall/p/12340866.html

时间: 2024-10-06 12:31:08

数据结构与算法系列二(复杂度分析)的相关文章

数据结构与算法系列四(单链表)

1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法?

数据结构与算法系列七(队列)

1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法?

数据结构与算法系列十三(选择排序)

1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法?

数据结构与算法系列 目录

最近抽空整理了"数据结构和算法"的相关文章.在整理过程中,对于每种数据结构和算法分别给出"C"."C++"和"Java"这三种语言的实现:实现语言虽不同,但原理如出一辙.因此,读者在了解和学习的过程中,择其一即可! 下面是整理数据数据和算法的目录表,对于每一种按照C/C++/Java进行了划分,方便查阅.若文章有错误或纰漏,请不吝指正.谢谢! 数据结构和算法目录表   C C++ Java 线性结构 1. 数组.单链表和双链表

深度解析(一)数据结构与算法系列目录

数据结构与算法系列 目录 最近抽空整理了"数据结构和算法"的相关文章.在整理过程中,对于每种数据结构和算法分别给出"C"."C++"和"Java"这三种语言的实现:实现语言虽不同,但原理如出一辙.因此,读者在了解和学习的过程中,择其一即可! 下面是整理数据数据和算法的目录表,对于每一种按照C/C++/Java进行了划分,方便查阅.若文章有错误或纰漏,请不吝指正.谢谢! 数据结构和算法目录表   C C++ Java 线性结构

前端数据结构与算法系列

数据结构与算法JavaScript版目录 数据结构与算法JavaScript (一) 栈 数据结构与算法JavaScript (二) 队列 数据结构与算法JavaScript (三) 链表

Java数据结构和算法(二)树的基本操作

Java数据结构和算法(二)树的基本操作 一.树的遍历 二叉树遍历分为:前序遍历.中序遍历.后序遍历.即父结点的访问顺序 1.1 前序遍历 基本思想:先访问根结点,再先序遍历左子树,最后再先序遍历右子树即根-左-右.图中前序遍历结果是:1,2,4,5,7,8,3,6. // 递归实现前序遍历 public void preOrder() { System.out.printf("%s ", value); if (left != null) { left.preOrder1(); }

数据结构与算法系列研究二——栈和队列

栈和队列的相关问题分析 一.栈和队列定义 栈和队列是两种重要的数据结构.从结构特性角度看,栈和队列也是线性表,其特殊性在于它们的基本操作是线性表的子集,是操作受限的线性表,可称为限定性的数据结构:从数据类型角度看,其操作规则与线性表大不相同,是完全不同于线性表的抽象数据类型.                    图1 栈的结构                                                 图2 队列的结构   1.1.栈是限定在表的一端进行插入和删除操作的线性

数据结构与算法系列十(排序算法概述)

1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法?