您当前的位置:首页 > 电脑百科 > 程序开发 > 算法

掌握这些数学函数,你会在算法效率的分析时经常用到

时间:2020-11-08 11:47:26  来源:  作者:
掌握这些数学函数,你会在算法效率的分析时经常用到

 

如何进行算法分析呢?

最简单方法是分别运行解决同一个问题的两个算法进行比较,但这样做法在很多时候并不理想。面对这样的困难迫使我们求助于数学工具,虽然我们不能对一个还没有完整实现的程序使用运行比较法,但却能通过数学分析了解程序性能的大致轮廓并预估改进版本的有效性。

大多数算法都有影响运行时间的主要参数 N,这里的 N 是所解决问题的大小的抽象度量,比如对于一个排序算法来说,N 是待排序元素的个数。我们的目标是尽可能地使用简单的数学公式,用 N 表达出程序的运行效率。

函数的增长

对于将要比较的两个算法,我们并不满足于简单地描述为“一个算法比另一个算法快”,而是希望能够通过数学函数直观地感受到二者的差异,具体来说,是希望知道“一个算法比另一个算法快多少”。

一些函数在算法分析中极为常见:

  1. 1。如果程序中的大多数指令只运行 1 次或几次,与问题的规模无关,我们就说程序运行的时间是常量的。小高斯的算法就是典型的常量时间。
  2. lg⁡N。随着问题规模的增长,程序运行时间增长较慢,可以认为程序的运行时间小于一个大常数。虽然对数的底数会影响函数的值,但影响不大。鉴于计算机是 2 进制的,所以通常取 2 为底数,lg⁡N=log2(⁡N),这与数学中略有差别(数学中 lg⁡N=log10⁡(N))。当 N=1024 时,lg⁡N=10;当 N 增长了 10 倍时,lg⁡N≈13,仅有略微的增长;只有当 N 增长到 N^2 时,lg⁡N 才翻倍。如果一个算法是把一个大问题分解为若干个小问题,而每个小问题的运行时间是常数,那么我们认为这个算法的运行时间是 lg⁡N,二分查找就其中的典型。
  3. √N。比 lg⁡N 稍大,当问题规模翻倍时,运行时间比翻倍少一点;当 N 增长了 100 倍时,程序运行时间增长 10 倍。开销是 √N 时间的程序通常对程序的终止条件做了处理,比如 ,在判断一个数是否是素数时,边界值是这个数的平方根,而不是这个数本身。
  4. N。这就是通常所说的线性时间,如果问题规模增大了 M 倍,程序运行时间也增大 M 倍。1 到 100 的蛮力求和法就是线性时间,这类方法通常带有一个以问题规模为终点的循环。
  5. N lg⁡N。当问题规模翻倍时,如果运行时间比翻倍多一点,我们就简单地说程序运行的时间是 N lg⁡N。当 N=1024 时,N lg⁡N=10240;如果 N=2048 ,N lg⁡N=22528。N lg⁡N 与 lg⁡N 都是把一个大问题分解为若干个能过在常数时间内运行的小问题,区别在于是否需要合并这些小问题,如果合并,就是 N lg⁡N;如果不合并,就是 lg⁡N。大多数归并问题的运行时间可以简单地看作 N lg⁡N。
  6. N²。如果问题规模翻倍,运行时间增长 4 倍;问题规模增长 10 倍,运行时间增长 100 倍。
  7. N³。如果问题规模翻倍,运行时间增长 8 倍;问题规模增长 10 倍,运行时间增长 1000 倍。
  8. 2^N。真正要命的增长。如果 N=10,2^N=1024;N 翻倍后,2^N=1048576。复杂问题的蛮力法通常具有这样的规模,这类算法通常不能应用于实际。

来看一下这些函数的增长曲线,如图 1 所示。

掌握这些数学函数,你会在算法效率的分析时经常用到

▲ 图 1 函数增长的曲线

以上函数能够帮助我们直观地理解算法的运行效率,让我们很容易区分出快速算法和慢速算法。大多数时候,我们都简单地把程序运行的时间称为“常数”、“线性”、“平方次”等。对于小规模的问题,算法的选择不那么重要,一旦问题达到一定规模,算法的优劣就会立马体现出来。代码 4-2 展示了当问题规模是 10、100、1000、10000、100000、1000000 时 lg⁡N 、√N 、N、N lg⁡N 、N² 、N³ 的增长规模。

▼代码 2 函数的增长规模 C4_2.py

01 import math
02
03 fun_list = ['lgN', 'sqrt(N)', 'N', 'NlgN', 'N^2', 'N^3'] # 函数列表
04 print(' ' * 10, end='')
05 for f in fun_list:
06     print('%-15s' % f, end='')
07 print('n', '-' * 100)
08
09 N_list = [10 ** n for n in range(7)] # 问题规模
10 for N in N_list: # 函数在不同问题规模下的增长
11     print('%-8s%-2s' % (N, '|'), end='')
12     print('%-15d' % round(math.log2(N)), end='')
13     print('%-15d' % round(math.sqrt(N)), end='')
14     print('%-15d' % N, end='')
15     print('%-15d' % round(N * math.log2(N)), end='')
16     print('%-15d' % N ** 2, end='')
17     print(N ** 3)

运行结果如图 4.2 所示。

掌握这些数学函数,你会在算法效率的分析时经常用到

 

图 2 告诉我们,该问题规模是 1 的时候,所有算法都同样有效,问题规模越大,不同复杂度的算法运行效率相差得越大。

2^N 增长得太过迅猛,作为一个另类单独列出。

▼ 代码 3 2^N 的增长

01 for N in range(10, 110, 10):
02 print('2**{0} = {1}'.format(N, 2 ** N))

运行结果如图 3 所示。

掌握这些数学函数,你会在算法效率的分析时经常用到

▲ 图 4.3 2^N 的增长

这些运行结果告诉我们,有些时候,选择正确的算法是解决问题的唯一途径。对于函数的输出结果来说,如果把 100 看作 1 秒,那么 10000 就是 100 秒,超过 1 分半。这意味着对于一个规模是 1000000 的问题来说,一个是 lg⁡N 复杂度的算法可以立刻得出结果,√N 复杂度的算法耗时约 10 秒,N 复杂度的算法耗时将超过 2.7 小时,N^3 复杂度则需要 3 万多年!也许我们可以忍受一运行 10 秒或 2.7 小时的程序,但一定没法容忍有生之年看不到结果的程序。



Tags:算法效率   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
如何进行算法分析呢?最简单方法是分别运行解决同一个问题的两个算法进行比较,但这样做法在很多时候并不理想。面对这样的困难迫使我们求助于数学工具,虽然我们不能对一个还没...【详细内容】
2020-11-08  Tags: 算法效率  点击:(101)  评论:(0)  加入收藏
▌简易百科推荐
前言Kafka 中有很多延时操作,比如对于耗时的网络请求(比如 Produce 是等待 ISR 副本复制成功)会被封装成 DelayOperation 进行延迟处理操作,防止阻塞 Kafka请求处理线程。Kafka...【详细内容】
2021-12-27  Java技术那些事    Tags:时间轮   点击:(1)  评论:(0)  加入收藏
博雯 发自 凹非寺量子位 报道 | 公众号 QbitAI在炼丹过程中,为了减少训练所需资源,MLer有时会将大型复杂的大模型“蒸馏”为较小的模型,同时还要保证与压缩前相当的结果。这就...【详细内容】
2021-12-24  量子位    Tags:蒸馏法   点击:(9)  评论:(0)  加入收藏
分稀疏重建和稠密重建两类:稀疏重建:使用RGB相机SLAMOrb-slam,Orb-slam2,orb-slam3:工程地址在: http://webdiis.unizar.es/~raulmur/orbslam/ DSO(Direct Sparse Odometry)因为...【详细内容】
2021-12-23  老师明明可以靠颜值    Tags:算法   点击:(7)  评论:(0)  加入收藏
1. 基本概念希尔排序又叫递减增量排序算法,它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的;希尔排序是一种不稳定的排序算法...【详细内容】
2021-12-22  青石野草    Tags:希尔排序   点击:(6)  评论:(0)  加入收藏
ROP是一种技巧,我们对execve函数进行拼凑来进行system /bin/sh。栈迁移的特征是溢出0x10个字符,在本次getshell中,还碰到了如何利用printf函数来进行canary的泄露。ROP+栈迁移...【详细内容】
2021-12-15  星云博创    Tags:栈迁移   点击:(19)  评论:(0)  加入收藏
一、什么是冒泡排序1.1、文字描述冒泡排序是一种简单的排序算法。它重复地走访要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地...【详细内容】
2021-12-15    晓掌柜丶韶华  Tags:排序算法   点击:(16)  评论:(0)  加入收藏
在了解golang的map之前,我们需要了解哈希这个概念。哈希表,又称散列表(Hash table),是根据键(key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算出一个键值的函数,将...【详细内容】
2021-12-07  一棵梧桐木    Tags:哈希表   点击:(13)  评论:(0)  加入收藏
前面文章在谈论分布式唯一ID生成的时候,有提到雪花算法,这一次,我们详细点讲解,只讲它。SnowFlake算法据国家大气研究中心的查尔斯·奈特称,一般的雪花大约由10^19个水分子...【详细内容】
2021-11-17  小心程序猿QAQ    Tags:雪花算法   点击:(24)  评论:(0)  加入收藏
导读:在大数据时代,对复杂数据结构中的各数据项进行有效的排序和查找的能力非常重要,因为很多现代算法都需要用到它。在为数据恰当选择排序和查找策略时,需要根据数据的规模和类型进行判断。尽管不同策略最终得到的结果完...【详细内容】
2021-11-04  华章科技    Tags:排序算法   点击:(37)  评论:(0)  加入收藏
这是我在网上找的资源的一个总结,会先给出一个我看了觉得还行的关于算法的讲解,再配上实现的代码: Original author: Bill_Hoo Original Address: http://blog.sina.com.cn/s/bl...【详细内容】
2021-11-04  有AI野心的电工和码农    Tags: KMP算法   点击:(36)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条