算法思想简介

以下是高德纳在他的著作计算机程序设计艺术里对算法的特征归纳:

  1. 输入:一个算法必须有零个或以上输入量。
  2. 输出:一个算法应有一个或以上输出量,输出量是算法计算的结果。
  3. 明确性:算法的描述必须无歧义,以保证算法的实际执行结果是精确地匹配要求或期望,通常要求实际运行结果是确定的。
  4. 有限性:依据图灵的定义,一个算法是能够被任何图灵完全系统模拟的一串运算,而图灵机只有有限个状态、有限个输入符号和有限个转移函数(指令)。而一些定义更规定算法必须在有限个步骤内完成任务。
  5. 有效性:又称可行性。能够实现,算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现。

算法的核心是创建问题抽象的模型和明确求解目标,之后可以根据具体的问题选择不同的模式和方法完成算法的设计。

穷举法

对于初学者来说,要解决一个问题,最简单最直接的方式莫过于穷举法,或者说暴力破解法。其基本思路是:对于要解决的问题,列举它所有可能出现的情况,从中获取问题的解。我不否认这种解决问题的方式是有效的、清晰的,但同时我们也应该清楚,现代计算机的计算速度是有限的。

穷举法也常用于对于密码和破译,即将密码进行逐个推算直到找出真正的密码为止。例如一个已知是四位并且全部由数字组成的密码,其可能共有10000种组合,因此最多尝试10000次就能找到正确的密码。理论上利用这种方法可以破解任何一种密码,问题只在于如何缩短试误时间。就像著名的非对称加密算法RSA,要破解RSA加密过数据不知道需要多少年。你可能会说,可以使用量子计算机,是的,这是可以的。但在计算机的计算力有限的前提下,我们应该如何缩短计算时间呢?

于是就有了各种算法,对于同一个问题,不同的算法差异在于它的时空复杂度。

递归法

  • 基本概念

函数调用自身的过程被称为递归。

我们第一次接触的递归大概都是谭浩强老师编写的教材上的斐波那契数列的例子吧。这是一个最基本、最明晰的递归调用。当我们要获取斐波那契数列中某一项的值时,一般我们是通过第一项加第二项得到第三项,在通过第三项加第四项得到第五项,依次类推,直到获得我们需要的值。

而在递归中,计算顺序似乎刚好颠倒了过来,从当前要计算的项一直推算到已知的项,这个已知的项就是递归的出口。其过程就好象剥洋葱一样,层层递进,将大问题转化成小问题。

递归算法的代码写起来是非常简洁的,但它并不是明晰的。我们的思维或许需要转个弯,而且它的时间复杂度相对是非常巨大的。对于斐波那契数列这个问题,使用另一种被称为迭代法的方法,它的代码看起来似乎有些繁琐,但它却是简单直接,时间复杂度较低的。

注意:

(1) 递归就是在过程或函数里调用自身;

(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。

  • 相关问题
  1. 斐波那契数列
  2. 汉诺塔
  3. 青蛙跳台阶

分治法

  • 基本概念

分治基本概念法是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这种算法设计策略叫做分治法。而递归就是采用了分治法的思想。

  • 特征

分治法所能解决的问题一般具有以下几个特征:

(1) 该问题的规模缩小到一定的程度就可以容易地解决;

(2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;

(3) 利用该问题分解出的子问题的解可以合并为该问题的解;

(4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加; 
第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;
第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。 
第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。

  • 基本步骤
  1.  分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题; 
  2.  解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题 ;
  3.  合并:将各个子问题的解合并为原问题的解。
  • 相关问题
  1. 二分搜索
  2. 大整数乘法
  3. Strassen矩阵乘法
  4. 棋盘覆盖
  5. 合并排序
  6. 快速排序
  7. 线性时间选择
  8. 最接近点对问题
  9. 循环赛日程表
  10. 汉诺塔

贪心算法

  • 基本概念

每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。

将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

  • 基本步骤
  1. 建立数学模型来描述问题 ;
  2. 把求解的问题分成若干个子问题; 
  3. 对每一子问题求解,得到子问题的局部最优解; 
  4. 把子问题的解局部最优解合成原来解问题的一个解。
  • 相关问题
  1. 活动选择问题
  2. 钱币找零问题
  3. 背包问题
  4. 小船过河问题
  5. 区间覆盖问题
  6. 销售比赛
  7. Huffman编码
  8. Dijkstra算法(求解最短路径)
  9. 最小生成树算法

动态规划法

  • 基本概念

每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。

将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

  • 特征

能采用动态规划求解的问题的一般要具有3个性质: 

  1. 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。 
  2. 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。 
  3. 有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)
  • 基本步骤
  1. 分析最优解的性质,并刻画其结构特征。 
  2. 递归的定义最优解。 
  3. 以自底向上或自顶向下的记忆化方式(备忘录法)计算出最优值 
  4. 根据计算最优值时得到的信息,构造问题的最优解
  • 相关问题        
  1. 矩阵连乘
  2. 走金字塔
  3. 最长公共子序列(LCS)
  4. 最长递增子序列(LIS) 
  5. 凸多边形最优三角剖分 
  6. 背包问题 
  7. 双调欧几里得旅行商问题
  8. Floyd-Warshall算法
  9. Viterbi算法

 

回溯法

  • 基本概念

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。 
回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 
许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。

在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 
若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。

  • 特征
  1. 针对所给问题,确定问题的解空间:首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解; 
  2. 确定结点的扩展搜索规则 ;
  3. 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
  • 相关问题
  1. 八皇后问题
  2. 图的着色问题
  3. 装载问题
  4. 批处理作业调度问题
  5. 背包问题
  6. 最大团问题
  7. 连续邮资问题
  8. 符号三角形问题

分支界定法

  • 基本概念

类似于回溯法,也是一种在问题的解空间树T上搜索问题解的算法。但在一般情况下,分支限界法与回溯法的求解目标不同。回溯法的求解目标是找出T中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解。
在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展对点。为了有效地选择下一扩展结点,以加速搜索的进程,在每一活结点处,计算一个函数值(限界),并根据这些已计算出的函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解。

  • 分支界定法与回溯法的区别
  1. 回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。
  2. 搜索方式的不同:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
  • 相关问题
  1. 装载问题
  2. 布线问题
  3. 背包问题
  4. 旅行售货员问题
  5.  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值