什么是算法

算法是什么

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。

五大特性

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

特性 描述
有穷性 算法的有穷性是指算法必须能在执行有限个步骤之后终止。
确切性 算法的每一步骤必须有确切的定义。
输入项 一个算法有 0 个或多个输入,以刻画运算对象的初始情况,所谓 0 个输入是指算法本身定出了初始条件。
输出项 一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的。
可行性 算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步骤,即每个计算步骤都可以在有限时间内完成(也称之为有效性)。

算法评定标准

同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。一个算法的评价主要从时间复杂度和空间复杂度来考虑。

时间复杂度

算法的时间复杂度是指执行算法所需要的计算工作量。一般来说,计算机算法是问题规模 n 的函数 f(n),算法的时间复杂度也因此记做。

T(n)=Ο(f(n))

因此,问题的规模 n 越大,算法执行的时间的增长率与 f(n) 的增长率正相关,称作渐进时间复杂度。

空间复杂度

算法的空间复杂度是指算法需要消耗的内存空间。其计算和表示方法与时间复杂度复杂度)类似,一般都用复杂度的渐近性来表示。同时间复杂度相比,空间复杂度的分析要简单得多。

正确性

算法的正确性是评价一个算法优劣的最重要的标准。

可读性

算法的可读性是指一个算法可供人们阅读的容易程度。

健壮性

健壮性是指一个算法对不合理数据输入的反应能力和处理能力,也称为容错性。

常见的算法思想

穷举法思想

穷举法,又称为强力法。它是一种最为直接,实现最为简单,同时又最为耗时的一种解决实际问题的算法思想。

基本思想:在可能的解空间中穷举出每一种可能的解,并对每一个可能解进行判断,从中得到问题的答案。

使用穷举法思想解决实际问题,最关键的步骤是划定问题的解空间,并在该解空间中枚举每一个可能的解。这里有两点需要注意,一是解空间的划定必须保证覆盖问题的全部解,二是解空间集合及问题的解集一定是离散的集合,也就是说集合中的元素是可列的、有限的。

穷举法用时间上的牺牲换来了解的全面性保证,因此穷举法的优势在于确保得到问题的全部解,而瓶颈在于运算效率十分低下。但是穷举法算法思想简单,易于实现,在解决一些规模不是很大的问题,使用穷举法不失为一种很好地选择。

递归与分治思想

递归与分治的算法思想往往是相伴而生的,它们在各类算法中使用非常频繁,应用递归和分治的算法思想有时可以设计出代码简洁且比较高效的算法来。

在解决一些比较复杂的问题,特别是解决一些规模较大得问题时,常常将问题进行分解。具体来说,就是将一个规模较大的问题分割成规模较小的同类问题,然后将这些小问题的子问题逐个加以解决,最终也就将整个大问题解决了。这种思想称之为分治。在解决一些问题比较复杂、计算量庞大的问题时经常被用到。

最为经典的使用分治思想设计的算法就是 “折半查找算法”。折半查找算法利用了元素之间的顺序关系(有序序列),采用分而治之的策略,不断缩小问题的规模,每次都将问题的规模减小至上一次的一半。

而递归思想也是一种常见的算法设计思想,所谓递归算法,就是一种直接或间接地调用原算法本身的一种算法。

贪心算法思想

贪心算法的思想非常简单且算法效率很高,在一些问题的解决上有着明显的优势。

先来看一个生活中的例子。假设有 3 种硬币,面值分别为 1 元、5 角、1 角。这 3 种硬币各自的数量不限,现在要找给顾客 3 元 6 角钱,请问怎样找才能使得找给顾客的硬币数量最少呢?你也许会不假思索的说出答案:找给顾客 3 枚 1 元硬币,1 枚 5 角硬币,1 枚 1 角硬币。其实也可以找给顾客 7 枚 5 角硬币,1 枚 1 角硬币。可是在这里不符合题意。在这里,我们下意识地应用了所谓贪心算法解决这个问题。

所谓贪心算法,就是总是做出在当前看来是最好的选择的一种方法。以上述的题目为例,为了找给顾客的硬币数量最少,在选择硬币的面值时,当然是尽可能地选择面值大的硬币。因此,下意识地遵循了以下方案:

  1. 首先找出一个面值不超过 3 元 6 角的最大硬币,即 1 元硬币。
  2. 然后从 3 元 6 角中减去 1 元,得到 2 元 6 角,再找出一个面值不超过 2 元 6 角的最大硬币,即 1 元硬币。
  3. 然后从 2 元 6 角中减去 1 元,得到 1 元 6 角,再找出一个面值不超过 1 元 6 角的最大硬币,即 1 元硬币。
  4. 然后从 1 元 6 角中减去 1 元,得到 6 角,再找出一个面值不超过 6 角的最大硬币,即 5 角硬币。
  5. 然后从 6 角中减去 5 角,得到 1 角,再找出一个面值不超过 1 角的最大硬币,即 1 角硬币。
  6. 找零钱的过程结束。

这个过程就是一个典型的贪心算法思想。因此,不难看出应用贪心算法求解问题,并不从问题的整体最优上加以考虑,它所作出的每一步选择只是在某种意义上得局部最优选择。因此,严格意义上讲,要使用贪心算法求解问题,该问题应当具备以下性质。

  1. 贪心选择性质

    所谓贪心选择性质,就是指所求解的问题的整体最优解可以通过一系列的局部最优解得到。所谓局部最优解,就是指在当前的状态下做出的最好选择。

  2. 最优子结构性质

    当一个问题的最优解包含着它的子问题的最优解时,就称此问题具有最优子结构性质。

我们经常使用的哈夫曼(Huffman Tree)编码算法,求解最小生成树的克鲁斯卡尔(Kruskal)算法和普利姆(Prim)算法,求解图的单源最短路径的迪克斯特拉(Dijkstra)算法都是基于贪心算法的思想设计的。

算法总结

一个算法应该具有以下五个重要的特征:有穷性、确切性、输入项、输出项和可行性。算法评定标准包括:时间复杂度、空间复杂度、正确性、可读性和健壮性。