数据结构与算法之美(一)——入门

简介:  掌握数据结构和算法,不管对于阅读框架源码,还是理解其背后的设计思想,都是非常有用的。一旦掌握数据结构和算法,之前可能需要费很大劲儿来优化的代码,需要花很多心思来设计的架构,用了数据结构和算法之后,很容易就可以解决了。

  《数据结构与算法之美》是极客时间上的一个算法学习系列,在学习之后特在此做记录和总结。

  掌握数据结构和算法,不管对于阅读框架源码,还是理解其背后的设计思想,都是非常有用的。一旦掌握数据结构和算法,之前可能需要费很大劲儿来优化的代码,需要花很多心思来设计的架构,用了数据结构和算法之后,很容易就可以解决了。

  数据结构和算法是相辅相成的,数据结构是为算法服务的,算法要作用在特定的数据结构之上。

  (1)从广义上讲,数据结构就是指一组数据的存储结构。算法就是操作数据的一组方法。

  (2)从狭义上讲,是指某些著名的数据结构和算法,比如队列、栈、堆、二分查找、动态规划等。

  该系列总结了 20 个最常用的、最基础数据结构与算法:

  (1)10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树;

  (2)10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法。


一、时间复杂度分析


  大 O 复杂度表示法,实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度。

  分析一段代码的时间复杂度有三个比较实用的方法:

  (1)只关注循环执行次数最多的一段代码。例如代码被执行了 n 次,所以总的时间复杂度就是 O(n)。

  (2)加法法则:总复杂度等于量级最大的那段代码的复杂度。例如两段代码的复杂度分别为O(n) 和 O(n^2),那么整段代码的时间复杂度就为 O(n^2)。

  (3)乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积。假设 T1(n) = O(n),T2(n) = O(n^2),则 T1(n) * T2(n) = O(n^3)


二、多项式量级


  这些复杂度量级几乎涵盖了你今后可以接触的所有代码的复杂度量级。


48.jpg


  非多项式量级只有两个:O(2^n) 和 O(n!)。接下来主要来看几种常见的多项式时间复杂度。

1)O(1)

  只是常量级时间复杂度的一种表示方法,并不是指只执行了一行代码。

  只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)。

2)O(logn)、O(nlogn)

  假设代码的执行次数是2^x=n,那么x=x=log2^n,因此这段代码的时间复杂度就是 O(log2^n)。

449.jpg


  假设有一段代码的时间复杂度是O(log3^n),而log3^n 就等于 log3^2 * log2^n,所以 O(log3^n) = O(C * log2^n),其中 C=log3^2 是一个常量。

  在采用大 O 标记复杂度的时候,可以忽略系数。所以,O(log2^n) 就等于 O(log3^n)。

  因此,在对数阶时间复杂度的表示方法里,我们忽略对数的“底”,统一表示为 O(logn)。

  如果一段代码的时间复杂度是 O(logn),我们循环执行 n 遍,时间复杂度就是 O(nlogn)。归并排序、快速排序的时间复杂度都是 O(nlogn)。

3)O(m+n)、O(m*n)

  m 和 n 是表示两个数据规模。

  因为无法事先评估 m 和 n 谁的量级大,所以在表示复杂度的时候,就不能简单地利用加法法则,省略掉其中一个。


三、空间复杂度分析


  时间复杂度的全称是渐进时间复杂度,表示算法的执行时间与数据规模之间的增长关系。

  类比一下,空间复杂度全称就是渐进空间复杂度(asymptotic space complexity),表示算法的存储空间与数据规模之间的增长关系。

  常见的空间复杂度就是 O(1)、O(n)、O(n2 ),像 O(logn)、O(nlogn) 这样的对数阶复杂度平时都用不到。


49.jpg



四、最好、最坏、平均、均摊时间复杂度


1)最好和最坏

  最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度。例如在最理想的情况下,要查找的变量 x 正好是数组的第一个元素。

  最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度。如果数组中没有要查找的变量 x,我们需要把整个数组都遍历一遍才行。

2)平均情况时间复杂度

  要查找的变量 x,要么在数组里,要么就不在数组里。为了方便理解,假设在数组中与不在数组中的概率都为 1/2。

  另外,要查找的数据出现在 0~n-1 这 n 个位置的概率也是一样的,为 1/n。

  所以,根据概率乘法法则,要查找的数据出现在 0~n-1 中任意位置的概率就是 1/(2n)。

  把每种情况发生的概率也考虑进去,那平均时间复杂度的计算过程就变成了这样:


50.jpg


  这个值就是概率论中的加权平均值,也叫作期望值,所以平均时间复杂度的全称应该叫加权平均时间复杂度或者期望时间复杂度。

  时间复杂度的大 O 标记法中,可以省略掉系数、低阶、常量,这段代码的加权平均时间复杂度仍然是 O(n)。

 

相关文章
|
3月前
|
机器学习/深度学习 人工智能 算法
深度学习入门:理解神经网络与反向传播算法
【9月更文挑战第20天】本文将深入浅出地介绍深度学习中的基石—神经网络,以及背后的魔法—反向传播算法。我们将通过直观的例子和简单的数学公式,带你领略这一技术的魅力。无论你是编程新手,还是有一定基础的开发者,这篇文章都将为你打开深度学习的大门,让你对神经网络的工作原理有一个清晰的认识。
|
1月前
|
机器学习/深度学习 算法 Python
机器学习入门:理解并实现K-近邻算法
机器学习入门:理解并实现K-近邻算法
36 0
|
2月前
|
机器学习/深度学习 算法
机器学习入门(三):K近邻算法原理 | KNN算法原理
机器学习入门(三):K近邻算法原理 | KNN算法原理
|
2月前
|
机器学习/深度学习 算法 大数据
机器学习入门:梯度下降算法(下)
机器学习入门:梯度下降算法(下)
|
2月前
|
机器学习/深度学习 算法 API
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
|
2月前
|
存储 机器学习/深度学习 算法
探索数据结构:入门及复杂度的解锁
探索数据结构:入门及复杂度的解锁
|
2月前
|
存储 缓存 应用服务中间件
Nginx入门 -- 基本数据结构中之ngx_hash_t
Nginx入门 -- 基本数据结构中之ngx_hash_t
43 0
|
2月前
|
存储 缓存 应用服务中间件
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
39 0
|
2月前
|
存储 应用服务中间件 nginx
Nginx入门 -- 基本数据结构中之ngx_str_t,ngx_array_t
Nginx入门 -- 基本数据结构中之ngx_str_t,ngx_array_t
82 0
|
2月前
|
机器学习/深度学习 算法
机器学习入门:梯度下降算法(上)
机器学习入门:梯度下降算法(上)