算法设计与分析-变治法

来源:互联网 发布:银行和程序员 编辑:程序博客网 时间:2024/05/17 09:08
变治法是指这样一组设计方法:它们都基于变换的思想。

这些方法都分为两个阶段变,把问题的实例变得更容易求解,治,在变的基础上对问题求解。


3种变换方式:

1)将问题变为一个更简单或方便的实例---实例化简(如预排序,高斯消去法)

2)变换同样的实例为不同的表现---改变表现(AVL树,多路查找树)

3)变换为另一个问题(这种问题的算法是已知的)的实例---问题化简(堆排序,其他等等,转化)



--------------------------------------------------------------------------------------------------------------------------------------------------


预排序可以作为一种其他算法的预处理技术,比较简单,主要是要有这种意识。高斯消去法是解线性方程组的算法,感觉主要是数学的东西,麻烦,只简单的介绍下,不实现。AVL树,多路查找树都是改变表现的变治策略,这都是数据结构里最难最麻烦的结构,以前也没实现过,就看了下理论,这里打算有时间写一下,算是自虐下。堆排序是一种问题变化的变治策略,前面写过。


---------------------------------------------------------------------------------------------------------------------------------------------------


1,预排序


准确的说,它不是一种算法设计策略,它是一种意识(你在设计算法时要有这种意识),往往在算法中作预处理,是一种将实例化简的变治策略。


1)检验数组元素的唯一性

若用蛮力,两遍扫描,一个个元素检查,复复杂度为n^2.

将数组排序后相同的元素就会挨着,扫描一遍即可检验元素唯一性,复杂度为n * log(n)。easy!



2)模式计算

模式是指一个序列中出现次数最多的一个数值。

若用蛮力,逐个检查出现次数,两遍扫描,复杂度为n^2.

预排序将相同的元素挨着,一遍扫描就可知道出现最多的元素,easy。


3)查找

蛮力为n,

若预排序,就可二分,复杂度为 n * log(n)  + log(n)  为n * log(n)

可以看到性能比蛮力还差,但若要进行多次的查找,这样还是值得的!


1),2),3)都很简单,算法伪代码和代码就不弄出来了。


关键是要有预排序的意识,排下序,你的问题也许就简单了一些


习题思考:





1,预排序,a[中间下表]即为所求。复杂度n * log(n) + 1  =  n * log(n)


2,a,预排序,然后扫描一遍,n * log(n) + n   =   n * log(n)

   b, 蛮力为n^2


3,一个经典问题,求两个集合的交集:清华数据结构第一章的问题,还可以求并集,差集


a,蛮力法对于A中的元素判断是否在B中,复杂度 m * n   (A,B中的元素个数为m,n)

b,把A,B的元素的放在一个数组中,预排序,扫描一遍取有连续的元素,复杂度(m + n) * log(m + n)


想想:

并集怎么做呢?----把A,B元素放在一个数组中,预排序,取全部元素(对连续元素去重),复杂度同上

差集怎么做呢?----似乎不能用上面的方法,但是却可以转换思路,根据集合的知识:A-B = 在A中减去A,B交集,或者A,B的并集减去B,转换为了求交集和并集,复杂度同上


4,

预排序:n * log(n) + 1  =  n * log(n)

蛮力:n

分治:n * log(n)



9,一道google笔试题



有点点难吧?

分析:

1)对于S = 0的情况,我们将问题转化为在数组A里来判断是否存在2个数是相反数

这里又可以用到预排序!!!---按绝对值大小顺序排序!!!,这样绝对值相等的数将挨着,只需一遍扫描就可判断是否存在相反数,时间复杂度为n * log(n)!!

2)但是题目并没有说S = 0啊,再转化一下,将数组每个元素减去S/2,然后来判断数组里面是否存在相反数(转化为问题(1))。

即:如果在原数组里存在   A[i]  +  A[j]   =  S,那么数组元素每个都减去了S/2,则刚才的A[i]  =  A[i]  -  S/2,  A[j]  =  A[j]  -  S/2.

这样在新数组里面就有A[i] + A[j]  =   ( A[i]  -  S/2)  +  ( A[j]  -  S/2)  =  0,即在新数组里判断是否存在相反数即可,转化为问题(1)

时间复杂度仍为n * log(n)


总结:

1)这道题的解决思路相当巧妙,也用到了预排序的思想,它是变形的预排序(按照绝对值大小预排序),这一点转化在分析1)中,能想到这一点已属不已。

2)更难想到的是2),有了1),你还需要继续转化,才能解决这个问题,其实转化也是一种变治思想,不断地将问题转化为便于解决或者已知某种解法的问题。


这道题充分的体现了变治的思想(预排序,问题转化),技巧性很高,google的题目真滴很有技巧性!!!



-------------------------------------------------------------------------------------------------------------------------------------------------


2,  高斯消去法


参见线性代数解线性方程组,都忘了,就是将系数矩阵化为一个上三角矩阵,具体的化法线性代数里面讲过

还有什么LU分解,求逆矩阵之类的,数学知识偏多,偏工程和计算,不去实现了,关键要知道它是一种变治和化简的策略。


--------------------------------------------------------------------------------------------------------------------------------------------------


3,平衡查找树


难难难,AVL树,红黑树是来实现二叉排序树平衡和相对平衡的一种策略,在超出平衡限制的时候通过旋转调整其平衡,用代码来实现这两个结构基本等于自虐(baidu算法男都这么说了)。

但对于理论,还是要比较清楚滴!(参见算法导论等相关书籍)

应该注意到,平衡树的策略就是为了改善二叉排序树的查找性能,它可以看做是改变二叉查找树表现形状的一种变治策略

另一种改变表现的策略是2-3树,2-4树,理论也是相当滴复杂,也是涉及到树的分裂,调整,了解一下思想即可。


--------------------------------------------------------------------------------------------------------------------------------------------------


4,堆和堆排序


堆也是数据结构里比较复杂,有一定实现难度的结构,参见前面文章:堆的链式实现,堆的数组实现。

关于堆的特征,概念,属性,实现,均参见上述2篇文章,这里不讨论这个。


从变治和问题化简的角度来说,堆可以干什么?

1)优先队列

2)堆排序

在实现了堆的基础上,这2个也是非常简单滴。


--------------------------------------------------------------------------------------------------------------------------------------------------


5,霍纳法则(改变表现形式


如果存在一个算法纪念堂,霍纳法则应该成为进入这个纪念堂的重要候选对象之一!它不仅高效和优雅,而且非常简洁(以至于这里我仅仅介绍下理论,实现就不写了,很easy!)

对于多项式,你怎么去计算快?

P(x) =  an * x^n   +  ......a1* x  + a0

一项项的计算?太慢了,每一项都要计算很多次乘法(求x的k次方)。

如果改变表现形式:



进行迭代,那么你只需要进行n次乘法即可!!!




实现非常简单,方法却十分巧妙!

霍纳法则是一个非常优秀的通过改变表现形式来解决问题的高效算法,值得注意的是,这一算法在发表150多年后,科学家们才注意到它的重要性,才意识到它在计算机中求解多项式时表现出的卓越性能。


--------------------------------------------------------------------------------------------------------------------------------------------------



6  问题化简与转化


例如在前面凸包问题中,判断一个点是否在左侧,是通过一个行列式来判断滴,将问题转化为一个数学上的式子。


1)求最小公倍数

两数相乘除以最大公约数,最大公约数算法已知。


2)线性规划

将一个问题转化为线性规划的约束问题


3)简化为图的问题

狼羊白菜问题,可以简化为图的问题。还有其他变形,都可以转化为图的问题,用图表示状态转移。求一条可达路径。


-------------------------------------------------------------------------------------------------------------------------------------------------


总结:

变治法可以说是不像分治,贪婪,动态规划那么标准,它更多的是一种思考的方式,把问题转化为易于解决的形式,或者转化为另一个问题。

0 0
原创粉丝点击