算法基础

一 算法的定义

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。

也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。

不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

image

一个算法应该具有以下七个重要的特征:

  1. 有穷性(Finiteness):算法的有穷性是指算法必须能在执行有限个步骤之后终止;
  2. 确切性(Definiteness):算法的每一步骤必须有确切的定义;
  3. 输入项(Input):一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件;
  4. 输出项(Output):一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;
  5. 可行性(Effectiveness):算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性);
  6. 高效性(High efficiency):执行速度快,占用资源少;
  7. 健壮性(Robustness):对数据响应正确。

二 时间复杂度

计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间,时间复杂度常用大O符号表述,使用这种方式时,时间复杂度可被称为是渐近的,它考察当输入值大小趋近无穷时的情况。

2.1 计算方法

我们将一个算法中的语句执行次数称为语句频度或时间频度,记为T(n)一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数f(n)因此,算法的时间复杂度记做:T(n) = O(f(n))。随着模块n的增大,算法执行的时间的增长率和f(n)的增长率成正比,所以f(n)越小,算法的时间复杂度越低,算法的效率越高。

在计算时间复杂度的时候,先找出算法的基本操作,然后根据相应的各语句确定它的执行次数,再找出T(n)的同数量级(它的同数量级有:1,log2n ,n ,nlog2n ,n^2,n^3等),找出后,f(n)=该数量级,若T(n)/f(n)求极限可得到一常数c,则时间复杂度T(n) = O(f(n))。

2.2 常见时间复杂度

按数量级递增排列,常见的时间复杂度有:常数阶O(1), 对数阶O(log2n),  线性阶O(n),  线性对数阶O(nlog2n),平方阶O(n^2), 立方阶O(n^3),..., k次方阶O(n^k), 指数阶O(2^n) 。其中:

1. O(n),O(n^2), 立方阶O(n^3),..., k次方阶O(n^k) 为多项式阶时间复杂度,分别称为一阶时间复杂度,二阶时间复杂度。。。。

2. O(2^n),指数阶时间复杂度,该种不实用

3. 对数阶O(log2n),  线性对数阶O(nlog2n),除了常数阶以外,该种效率最高

它们按照效率,由小到大依次为:

Ο(1)<O(log2n)<Ο(n)<Ο(nlog2n)<Ο(n^2) < O(n2log2n)2) < Ο(n^3)<… …<Ο(2^n)<Ο(n!)

2.3 举例说明时间复杂度的计算

# O(n)
n = 5                       # 频度:1
for i in range(n):          # 频度:n
    print('Hello world')    # 频度:n
# 说明:T(n) = 2n+1 = O(n)


# O(n^2)
for i in range(n):              # 频度:n
    for j in range(n):          # 频度:n^2
        print('Hello world')    # 频度:n^2
# 说明:T(n) = 2n^2+n+1 = O(n^2)

for i in range(n):              # 频度:n
    print('Hello world')        # 频度:n
    for j in range(n):          # 频度:n^2
        print('Hello world')    # 频度:n^2
# 说明:T(n) = 2n^2+2n = O(n^2)


# O(log2n)/O(logn)
n = 64
while n >= 1:
    print(n)
    n = n // 2
# 说明:设定循环的频度是f(n),则:2^f(n)<=n;f(n)<=log2n,所以,循环减半的时间复杂度为O(log2n),即T(n) = O(log2n)或者O(logn)


# O(n^3)
for i in range(n):                  # 频度:n
    for j in range(n):              # 频度:n^2
        for k in range(n):          # 频度:n^3
            print('Hello world')    # 频度:n^3
# 说明:T(n) = 2n^3+n^2+n = O(n^3)

2.4 怎样快速判断时间复杂度

  1. 循环减半的过程 ----> O(logn)
  2. 几次循环就是n的几次方的复杂度

补充:时间复杂度分为三种:

  • 最优时间复杂度 (Best-Case)
  • 平均时间复杂度 (Average-Case)
  • 最差时间复杂度 (Worst-Case)

最差时间复杂度的分析给了一个在最坏情况下的时间复杂度情况,这往往比平均时间复杂度好计算,而最优时间复杂度一般没什么用,因为没人会拿一些特殊情况去评判这个算法的好坏。

三 空间复杂度

用来评估算法内存占用大小的一个式子

a = 100  # 空间复杂度为1

# 空间复杂度为1
a = 100
b = 200
c = 300

L = [1, 2, 3, 4, 5]  # 空间复杂度为5

L = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]  # 空间复杂度为5*4

L = [[[1, 2], [1, 2]], [[1, 2], [1, 2]], [[1, 2], [1, 2]]]  # 空间复杂度为3*2*2

说明:定义一个或多个变量,空间复杂度都是为1,列表的空间复杂度为列表的长度

 

更多可参考:http://www.cnblogs.com/alex3714/articles/5474411.html

posted @ 2018-06-13 17:43  Joe1991  阅读(117)  评论(0)    收藏  举报