小崔的advice
(1)蛮力穷举法,可以说可以解决所有的问题,不过对于组合数很大的问题时间性能不是很好甚至不能忍受。例子:全排列的生成、n选m组合的生成(这两个的 蛮力法都可以利用多重嵌套循环形成,层次很壮观),8皇后问题(对应成8数全排列),12城tsp问题(对应成12数排列),a的n次方计算就老老实实连 乘n次a,顺序查找元素等都是蛮力穷举的例子。
(2)分治法,就是把1个大问题分成2个小问题,2个小问题还可以再分,直到问题规模小的可以简单解决。处理每个小问题,把处理结果汇总处理, 最后得到整个大问题的解。一般而言,分治法都要用到递归。例子:算n个数的和,可以算前一半n/2的和,后一半n/2的和,最后相加即得总和;凸包问题, 可以把最左边点和最右边点连线,右上边点集的凸包(叫做上包)和下面点集的凸包(叫做下包),最后把上包和下包合围起来就是整个凸包。点集的最小点对问 题,可以以一条线为界,分成左右两个集合,分别求最小点对,最后在合起来处理。分治法对多个处理器或处理机的并行计算特别适用。
(3)减治法,就是处理过程中问题规模不断减小的方法。最常见的就是折半查找,每次都把n/2个元素删去;减治法一半分为减1法,减常数法,减 可变规模法。减1法典型的就是插入排序,还有计算a的n次方,可以计算a的n-1次方,再变成计算a的n-2次方等等。想查找二叉树的查找都利用了减治的 思想。
(4)变治法,就是对问题进行变相,变化,利用已有的解决方案来解决生疏的问题,重点在于对原来的生疏问题进行转化,转变,使他变成一个已有好的解法的熟悉问题。
(5)时空权衡,考虑时间和空间的相互转化,有时利用空间换时间,有时利用时间换空间,常用的就是 计数排序(多利用了一个计数数组),散列法,B树。
(6)动态规划,也是时空权衡的一种,把可重复的问题的解保存在一个表里面。例子包括 计算二项式系数,最有二叉查找树,背包问题和记忆功能。
(7)贪婪算法,就是每一步都从可选方案中选择对该步最有利的方案,直到问题解决。贪婪法有可能得不到问题的最优解,不过得到的解一般都很接近问题的最优解。它的优点就是效率高,时间复杂性相对有那些得到最优解的算法快很多。常用的例子:
最小生成树的prim算法,kruskal算法,最短路径的dijkstra算法,解决tsp问题。
(8)回溯法
(9)分支限界法 (8)(9)很类似,回溯法基于深度优先搜索,而分支限界一般基于宽度优先搜索。
学了数据结构和算法,对一些思想大概了解,但还需要亲自实现实现,否则就只能侃侃而谈。
(1)数组,串的逆序生成,串匹配。
(2)链表的遍历,添加元素,删除元素。
(3)栈的实现。
(4)队列的实现。
(5)树的存储,建立,遍历,元素查找,平衡二叉树的添加、删除元素。
(6)图的2种存储方法和图算法的实现。
(7)常见查找方法的实现,最基本的顺序查找,折半查找。
(8)常见排序方法的实现,最基本的插入排序,冒泡排序,选择排序,技术排序,归并排序,堆排序,快速排序,希尔排序。
不妨先把上面的弄熟,再慢慢利用stl的标准容器和算法,当然追求迅速编程也可直接stl。
弄熟上面的是我们必须的,我也在努力。
(1)找零钱问题 (贪婪,最优解,编程应该很快).
(2)很快编一个 二分查找的程序.
(3)很快编一个 快速排序的程序.
(4)很快便一个 归并排序的程序.
(5)大数乘法 (分治法)
(6)利用(2)作为函数,实现 大数阶乘(纯属编程练习)
(7)二叉树的遍历(先序,后序,中序) (利用递归吧,递归练习,建立树后应该很快).
(8)平面最近点对问题(分治法,递归,学会分析问题)
(9)最小生成树,最短路径,拓扑排序(最基本的图论问题,贪婪算法)
(10)连续的背包问题(贪婪) 离散的0/1背包问题 (对子集树进行回溯)
(11)C(n,m)的计算(动态规划的最基本的例子)
(12)TSP问题(对排列树进行回溯)
推荐两本书: 算法设计与分析 潘彦 (译)
计算机算法设计与分析 王晓东 (其实很不错).
没有评论:
发表评论