【算法】蚕食《算法导论》 -- 01

336 阅读5分钟

算法在计算中的作用

1.1 算法

非形式的说,算法就是任何良定义的计算过程

所以,在这句话里,我们可以这样理解: 算法本质上是一个计算过程,然后是什么的计算过程呢?它是任何良定义的计算过程。既然是个计算过程,那么就肯定有输入和输出(结果),因此,我们把这个计算过程中某个值或者值的集合作为输入,对应的,我们把输入之后产生的某个值或者值的集合作为输出。

image.png

就像上面的图所示,算法可以理解为:就是把输入转换成输出的计算步骤的一个序列。

除了上面这个把算法视为计算过程的角度之外,还有一个角度,那就是把算法视为一种工具,一种用于求解良说明的计算问题的工具。

一般来说,问题陈述说明了期望的输入/输出关系。 而算法则描述一个特定的计算过程,来实现该输入/输出关系。

什么意思呢,我们通过力扣上的算法题来理解这一句话。

image.png

图片上的是一道算法题,红色框框中的就是问题陈述部分,它描述了我们所期望的输入与输出的关系,什么关系呢?根据题目我们可以知道,输出的两个数组下标在数组中对应的元素的值相加之后会等于target的值,这就是这道题目中输入与输出的期望关系。

在上面这道题目中,我们将每一个输入序列称为该问题的一个实例。 一般而言,每个问题都会有很多个实例,但是并不是所有输入都可以称为是这个问题的实例的。

一般来说,问题的实例由该问题解所必须的(满足问题陈述中强加的各种约束)输入组成。

也就是说,像下面的这种输入是不能称为该问题的实例的:

nums = 1, target = 9
nums = [1,2,3,4], target = 3.14
nums = ['apple', 'orange', 'pine'], target = 'gaga'

因为上面的这些输入都没有满足问题陈述中强加的各种约束(nums必须为整数数组,target必须为整数)。

如果在力扣上刷过题应该都知道,某一道题的算法是会分对错的,当然,这个对错指的是某个算法是否能解决当前问题,能解决我们说这个算法是对的,反之则说这个算法对这个问题而言是不对的。 注意到了吗,这里是加了限制条件的,因为同一个算法,对不同的问题所能达到的效果是可能不一样的,所以算法的对错只针对它所要解决的问题而言。

如果有一个算法,对问题的每个输入实例,这个算法都会给出正确的输出停机,那么我们称该算法是正确的,并称正确的算法解决了给定的问题。

不正确的算法一定没用吗?其实也不是的,不正确的算法只要其错误率可控有时候可能还是有用的。

算法的描述形式有很多种,比如说你可以将算法用英文来说明,也可以将算法写成一个计算机程序,或者你甚至可以用硬件设计来描述它也行,对算法的描述的样式是多种多样的,但是要求只有一个,那就是这个描述方式必须可以精确的描述算法所要遵循的计算过程。

数据结构

数据结构是一种存储和组织数据的方式,旨在便于访问和修改。不存在一种通用或者说适用于所有用途的单一数据结构。

也就是说,每种数据结构都有其优势和其局限性,所以我们要根据我们所需要解决的问题去选择适合的数据结构。

NP完全和NP不完全问题

我们对算法的关注点一般都是算法的效率的高低,而我们对效率的量度一般是速度,也就是说,我们关心的一般是一个算法需要花费多长时间才能产生结果。

但是,有一些问题,目前还不知道有效的解法。这种问题被我们称为是NP完全的

NP完全问题有以下几点特性:

  1. 至今为止,不曾找到一个对NP完全问题的有效算法,但是,也没人能证明NP完全问题确实不存在有效解法。
  2. 如果任何一个NP完全问题存在有效解法,那么所有的NP完全问题都存在有效解法。
  3. 有几个NP完全问题类似于一些存在着已知有效算法的问题。

我们关注NP完全问题的意义在于,当我们在实际应用中遇到的时候,避免花费许多时间在可能毫无结果的探寻中寻找有效解法,如果我们能证明这个问题是NP完全的,那么我们可以选择开发一个有效的算法,这个算法给出的是好的解,但不必一定是最好的解。

而想这种给出好的解的有效算法,存在一个有效算法给出的解离最小可能解不太远,我们称这个算法为近似算法