算法( Algorithm ):
是指用阿拉伯数字进行算术运算的过程。在中世纪时,珠算家用算盘进行计算,而算术家用算术进行计算。
算法应该具有以下几个重要的特征:
有穷性:保证在执行了有限的步骤之后然后结束 。
输入:每个算法有零个或多个输入,以刻画运算对象的初始情况,所谓零个输入是指算法本身 ,除了初始条件;
输出:每个算法有一个或多个输出,显示对输入数据加工后的结果。没有输出的算法是毫无意义的;
可行性:原则上算法能够精确地运行,进行有限次运算后即可完成一种运算。
计算机中,算法可分为两大类:
数值运算算法: 求解数值。
非数值运算算法:事务管理。
算法是计算机处理信息的根本,因为计算机程序本质上是一个算法,告诉计算机确切的步骤来执行一个指定的任务。当算法在处理信息时,会从输入设备上读取数据,写入输出设备,也可能保存起来以供以后使用。
沃斯公式;
数据结构+算法=程序
一个程序应当采用结构化程序设计方法进行程序设计,并且用某一种计算机语言来表示。因此,可以用下面的公式表示。
程序=算法+数据结构+程序设计方法+语言和环境
常见的算法思想解析(不深究)
-
简单暴力的 穷举法
穷举法 (ExhaustiveAttack method) 又称枚举法 。它是穷尽每一种可能的组合情况, 效率不高,适用于没有明显规律的情况。也是最为耗时的一种解决实际问题的算法思想。
穷举法也是一种针对于密码的破译方法,我们称为暴力破解 。假如一个五位并且全部由数字组成其密码共有1000种组合,也就是说最多我们会尝试999次才能找到真正的密码。利用这种方法我们可以运用计算机来进行逐个推算,也就是说用我们破解任何一个密码也都只是一个时间问题,缺点是如果数据量巨大。如果密码位数多而且类型多样的的话,会导致时间极度漫长甚至崩溃。
设计思想: 在可能出现的解决方案里面,穷举出每一种可能,并对每一种可能进行判断从而得出结果。
-
稍微聪明的 递推法
递推: 从小到大,从已知到未知。 通过已知条件,利用特定关系逐步递推,最终得到结果为止,核心就是不断的利用现有信息推导出新的东西。
递推 分为 :
逆推:从结果推出条件
顺推:从条件推出结果 典型例子为:“斐波那契”数列 。
-
调用自己的 递归法
递归(recursion),就是一种直接或间接地调用原算法本身的一种算法,与递推不同的是 它是 从未知到已知,从大到小,再从小到大。
在程序中不断反复调用自身来达到求解问题的方法。这里的重点是调用自身,这就要求待求解的问题能够分解为相同问题的一个子问题。这样 ,通过多次递归调用,便可以完成求解。 这就是递归算法
下面举一个我们在Java 中用文件操作比较多的一个方法, 遍历文件夹文件。
遍历显示C盘下的所有文件夹及其文件 public static void main(Stirng[] args){ File c = new File(" c:/"); showAll(c) } public static void showAll(File dir){ File[] fs = dir.listFiles(); for (File file : fs){ if(file.isDirectory()){ showAll(file); // 在这儿调用本方法 , 实现自己调用自己 }else{ system.out.println(file.getPath()); } } }
函数的递归调用分两种情况:直接递归和间接递归。
- 直接递归:即在函数中调用函数本身。
- 间接递归:即间接地调用一个函数,如 方法 1 调用 方法 2 方法 又2 调用方法 1。间接递归用得不多。
-
各个击破的 分治法
递归与分治的算法思想往往是相伴而生的,它们在各类算法中使用非常频繁,应用递归和分治的算法思想有时可以设计出代码简洁且比较高效的算法来。在解决一些比较复杂的问题,特别是解决一些规模较大得问题时,常常将问题进行分解。具体来说,就是将一个规模较大的问题分割成规模较小的同类问题,然后将这些小问题的子问题逐个加以解决,最终也就将整个大问题解决了。这种思想称之为分治。在解决一些问题比较复杂、计算量庞大的问题时经常被用到。
最为经典的使用分治思想设计的算法就是“折半查找算法”。折半查找算法利用了元素之间的顺序关系(有序序列),采用分而治之的策略,不断缩小问题的规模,每次都将问题的规模减小至上一次的一半。
-
子问题联系的 动态规划法
基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。
与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。
-
局部最优的 贪心法
何为贪心算法?
贪心算法 是指 在对问题求解时,总是做出在当前看来是最好的选择, 也就是说,不从整体来考虑,做出在某种意义上的局部上的最佳方案。
贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。
-
迷宫一样的 回溯法
回溯顾名思义,返回去。实际上是一个类似于枚举法的寻找解决方案的过程。主要是在寻找过程中寻找问题的解决方案。当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。(好像有点类似于数据库事务的回滚rollback)。