算法:初识算法

Web

作为一名光荣的新时代农民工,虽然只是小前端,但是算法这种洋气的东西怎么能完全不会呢?!!!

这是什么?是算法,学一学!这是什么?是算法,学一学!这是什么?是算法,学一学!

内容源于:「Hello 算法」

算法是什么?

算法定义

「算法 Algorithm」,是在有限时间内解决特定问题的一组指令或操作步骤。

算法具有以下特点:

  • 问题是明确的,具有清晰的输入和输出定义。
  • 解具有确定性,即给定相同的输入时,输出始终相同。
  • 具有可行性,在有限的步骤、时间和内存空间下可完成。

数据结构定义

「数据结构 Data Structure」,是计算机中组织和存储数据的方式。

为了提高数据存储和操作性能,数据结构的设计目标包括:

  • 空间占用尽量减少,节省计算机内存。
  • 数据操作尽可能快速,涵盖数据访问、添加、删除、更新等。
  • 提供简洁的数据表示以及逻辑信息,以利于算法的高效运行。

数据结构与算法的关系

「数据结构」与「算法」高度相关且紧密结合,具体表现在:

  • 数据结构是算法的基石。数据结构为算法提供了结构化存储的数据,以及用于操作数据的方法。
  • 算法是数据结构发挥的舞台。数据结构本身仅存储数据信息,通过结合算法才能解决特定问题。
  • 特定算法通常有对应最优的数据结构。算法通常可以基于不同数据结构进行实现,但最终执行效率可能相差很大。

如果类比成 LEGO 的话,则关系如下图所示:

数据结构与算法 LEGO
输入数据 未拼装的积木块
数据结构 积木的组织形式,包括形状、大小、连接方式等
算法 把积木拼成目标形态的一系列操作步骤
输出数据 成品的积木模型

算法效率评估

算法评价维度

从总体上看,算法设计追求以下两个层面的目标:

  1. 找到问题解法。算法需要在规定的输入范围内,可靠地求得问题的最优解。
  2. 寻求最优解法。同一问题可能存在多种解法,我们希望找到尽可能高效的算法。

因此,在能够解决问题的前提下,算法效率成为主要的评价维度,主要包括:

  • 时间效率,即算法运行速度的快慢。
  • 空间效率,即算法占用内存的大小。

简而言之,我们的目标是设计既快又省的数据结构与算法。掌握评估算法效率的方法则至关重要,因为只有了解了评价标准,我们才能进行算法之间的对比分析,从而指导算法设计与优化过程。

效率评估方法

实际测试

假设我们现在存在算法 A 和算法 B,它们都能解决同一问题,现在需要对比这两个算法的效率。我们最直接的方法就是找到一台计算机,运行这两个方法,并且监控记录它们的运行时间和内存占用情况,这种评估方式能够反映真是情况,但也存在较大局限性。

难以排除测试环境的干扰因素。硬件配置会影响算法的性能表现。例如,在某台计算机中,算法 A 的运行时间比算法 B 短;但在另一台配置不同的计算机中,我们可能得到相反的测试结果。这意味着我们需要在各种机器上进行测试,而这是不现实的。

展开完整测试非常消耗资源。随着输入数据量的变化,算法会表现出不同的效率。例如,输入数据量较小时,算法 A 的运算时间可能短于算法 B;而输入数据量较大时,测试结果可能相反。因此,为了得到有说服力的结论,我们需要测试各种规模的输入数据,这样需要占用大量的计算资源。

理论评估

由于实际测试具有较大的局限性,我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为「复杂度分析 Complexity Analysis」或 「渐进复杂度分析 Asymptotic Complexity Analysis」。

复杂度分析评估的是算法运行效率随着输入数据量增多时的增长趋势。这个定义有些拗口,我们可以将其分为三个重点来理解:

  • “算法运行效率” 可分为 “运行时间” 和 “占用空间”,因此我们可以将复杂度分为「时间复杂度 Time Complexity」和「空间复杂度 Space Complexity」;
  • “随着输入数据量增多时” 表示复杂度与输入数据量有关,反映算法运行效率与输入数据量之间的关系;
  • “增长趋势” 表示复杂度分析关注的是算法时间与空间的增长趋势,而非具体的运行时间或占用空间;

复杂度分析克服了实际测试的弊端。首先,它独立于测试环境,因此分析结果适用于所有运行平台。其次,它可以提现不同数据量下的算法效率,尤其是大数据量下的算法性能。

数组与链表

数组

优点

在数组中访问元素非常高效。由于数组的元素被储存在连续的内存空间中,因此计算数组元素的内存地址非常容易。

访问元素的高效性带来了诸多便利。例如,我们可以在O(1)时间内获得数组中的任意一个元素。

缺点

数组在初始化后长度不可变。由于系统无法保证数组之后的内存是可用的,因此数组长度无法拓展。而若希望拓展数组,则需要新建一个新数组,然后把原本数组元素依次拷贝进新数组,在数组很大的情况下,这是非常耗时的。

数组中插入或删除元素效率低下

本文作者:Kiro

本文链接: https://www.kiro.cc/2023/05/algorithm/