开篇词

开篇词 | 算法是程序的“灵魂”

大家好,我是王晓华,网名 orbit。2015 年出版了一本书,名为《算法的乐趣》,以“趣味性”为着手点,介绍了二十多个趣味算法的原理和实现,主要目的是希望读者了解到算法并非是枯燥、抽象的代码,算法的设计和应用是一件十分有趣的事情。做为一本非典型的算法书,许多读者学习后觉得意犹未尽,希望能以更系统的方式来介绍各类算法的设计和实现,同时介绍更多分析问题的方法和抽象问题数据模型的技巧,而这正是本课程的目标。

课程背景

算法在程序中扮演着非常重要的角色,有人将数据结构比喻为程序的骨架,将算法比喻为程序的灵魂,这一点也不为过。正是因为这一点,很多朋友都立志要学好算法,但是我常常看到各种抱怨,比如“看了半年《算法》这本书,才看了几十页”,再比如“四年了,还是没有啃完《算法导论》”。出现这种情况的主要原因有两个,其一是算法纷繁复杂、知识点多,没有一种放之四海而皆准的通用规则,很难一下子从总体上掌握全貌;其二是一些算法虽然有常用的设计模式,但是不同的问题有不同的数学模型,需要设计好数学模型才能带入算法模式进行求解,然而设计数学模型对新手来说通常是个高高的门槛。

人们设计各种算法的目的是解决现实中的问题,虽然各种算法的实现五花八门,但是设计算法却有一些通用的方法或思想(也有的资料将其称为算法设计模式)。归纳起来,这些常见的算法设计方法有迭代法、穷举搜索法、分支界限法(剪枝法)、递推法、递归法、回溯法、分治法、贪婪法和动态规划法等。

本课程选择了三十多个简单且实用的算法实例,这些算法实例基本覆盖了各种算法比赛中经常出现的题目以及生活中常见的一些有趣的算法实现。每个算法实现都将讲解的侧重点放在各种算法的设计方法和思想在算法中的体现,通过一个个算法例子,来引导大家掌握常见的算法设计思想。除此之外,在算法实现的过程中,还会详细介绍针对各个问题的建模过程,使读者能够举一反三,学会如何将文字描述的问题抽象为算法能够使用的数据模型。总之,本课程的目的不是学会这些算法,而是通过学习这些算法的实现,掌握算法设计的方法,以后遇到类似的问题,可以自己设计并实现解决问题的算法。

课程大纲

前面介绍的各种算法设计方法并不是孤立存在的,很多算法最终的实现都是几种算法思想在一起融合后的产物。例如,穷举搜索法常常要结合递归和回溯操作实现穷举遍历,有时候还需要借助分支界限法“剪掉”一些重复的分支或明显不可能存在解的分支,目的是提高穷举的效率;再比如很多读者望而生畏的动态规划法,其递推关系的确定体现的就是递推的思想;再再比如,迭代法通常结合分治的思想,使得每次迭代都能把大问题分解为一系列容易求解的小问题。有一些设计方法可以单独成为一个主题,有些设计方法无法单独列为一个主题进行讲解,本课程前半部分根据常见的算法题目,重点介绍迭代、穷举和动态规划三个主题,三个主题共计 18 个算法实例,基本上涵盖了上述所有算法设计方法和思想的应用。本课程后半部分则通过 24 个有趣的算法实现,让大家理解算法的重要性,但重点仍然是各种算法设计思想的应用和如何设计适用于算法的数据模型。

本课程的目的是培养大家解决实际问题的能力,每篇介绍一个算法问题,通过对这个问题的分析和解决,锻炼大家针对问题设计数据模型,并应用合适算法思想设计出解决问题的算法实现的能力。

本课程分为七大部分,共计 43 篇。

第一部分(第 1-1 ~ 1-7 课):基础

这部分内容共有 7 课,第 1-1 课为算法基础内容,介绍了将问题抽象成数据建模的常用方法。第 1-2 ~ 1-6 课介绍了 5 种常用的算法设计思想(模式),分析了各种算法模式的特点和使用时需要注意的要点,每种模式都用一 ~ 两个具体的算法做示例。第 1-7 课介绍了一些基础算法和技巧,比如排序、单链表逆序和用数组存储树等小算法,作为本课程开始之前的热身或开胃菜。

第二部分(第 2.1 ~ 2.3 课):迭代和递推

这部分内容通过 3 个在数学领域常用的数值分析方法,介绍了迭代思想在算法设计中的应用,涉及的内容还包括了如何将数学公式或文字描述的递推关系转化为数据模型的方法。   

第三部分(第 3-1 ~ 3.7 课):穷举搜索

这部分内容通过 7 个不同的算法实例,介绍了几种常见的穷举方法,比如线性数字类问题的穷举方法、树形空间的穷举方法、棋盘类游戏的常用穷举方法以及复杂问题的多重穷举和组合穷举方法,重点介绍了如何设计与穷举算法相适应的数据模型,以及用合理的数据模型简化算法实现的技巧。

第四部分(第 4.1 ~ 4.7 课):动态规划

这部分找了 7 个有趣的算法,其中一些是算法比赛中曾经出现的题目,一些是动态规划的典型问题,既有简单的线性(一维)动态规划和二维动态规划问题,也有凸多边形的三角剖分、矩阵链乘这样的热点问题。动态规划最重要的是划分阶段和确定状态(确定递推关系式),通过这些例子,可以了解如何建立问题对应的数据模型以及建立在数据模型上的递推关系式。掌握这些方法,再遇到动态规划类的问题时,就不会束手无策了。

第五部分(第 5.1 ~ 5.5 课):图论

图论即是各种算法比赛中出题的“重灾区”,也是现实生活中很多有趣算法的理论基础,这部分选择了 5 个有趣的算法,讲解的重点仍然是各种算法设计的思想和建立数据模型。

第六部分(第 6.1 ~ 6.6 课):游戏中常用的算法

这部分内容将介绍 6 个趣味算法,介绍的内容包括决策树、博弈树和行为树的搜索算法,涉及的内容包括穷举、递归和分支界限法等算法思想的应用。其中,棋类游戏和俄罗斯方块游戏的算法,都是非常经典的算法,掌握这些经典的算法思想,有助于读者掌握各种解决各种决策、博弈类问题的解决方法。此外,这部分内容还介绍了经典的高效棋盘数据模型、估值函数和状态 hash 算法等程序代码设计技巧,学习完这些技巧将有助于开阔思维,提升代码能力。

第七部分(第 7.1 ~ 7.7 课):算法与应用

这部分内容将介绍 7 个算法,都是一些名声远扬的公开的算法,不需要我们重新设计,介绍这些算法的目的是希望大家了解这些高大上算法中都使用了哪些算法设计思想。另外,这些算法都是一些模板算法,要想解决具体的问题,需要对具体问题建模,然后再套用这些算法模板以形成具体的算法。

课程寄语

尽管算法设计的常用方法有很多,但是这些方法之间并不是互相孤立的。比如,有些递推关系可以通过迭代法实现,如牛顿迭代法,还有些递推关系需要通过广域搜索来实现,比如常见的动态规划算法。贪婪法很少单独用于解决最优解问题,但是贪婪法的思想体现在很多算法中,比如著名的“Dijkstra 算法”,在确定某个顶点的下一个最短路径点时,就使用了贪婪法的思想,每次选择距离最近的那个点作为下一个顶点。本课程将会在剖析这些算法的原理的过程中,为大家指出各种算法设计思想的体现,以加深对算法设计常用方法的认识。

本课程的目的不是告诉读者这些问题的解决方案,因为很多问题的算法都是已经实现的公开算法(各种顶着光环的“XXX”算法),重复这些内容毫无意义。“授人以鱼不如授人以渔”,我们希望在对每个算法的分析、分解和实现的过程中,让读者掌握设计算法的方法和一些常用的技巧。通过学习本课程的内容,读者在面对各种算法问题时,可以摆脱之前的束手无策状态,能够自己设计算法解决问题。

希望大家通过本课程的学习,将掌握算法设计常用的思想和技巧,提升将具体问题抽象(转化)为数据模型的能力,了解各种设计算法常用的代码技巧,提高动手能力,今后遇到复杂算法问题或再啃各种大块头算法书籍的时候,能够轻松应对。最后,预祝大家学习愉快!

上一篇
下一篇
目录