(3更)算法总结

作者: 凉拌姨妈好吃 | 来源:发表于2018-04-10 11:35 被阅读0次

    贪心算法

    Q:什么是贪心算法?

    A:不管最后怎么样,先获得当前的最优解。所以贪心算法最后得到的解并不一定是最优解

           例子:一个袋子可以装4斤水果,现在有3斤苹果,2斤草莓,2斤葡萄,贪心算法就会直接先把苹果装进去,其实最优的是装2斤草莓2斤葡萄!

    相关应用:

    Prim算法、Kruskal算法、喷泉问题、会场问题、过河问题、01背包问题

    什么是Prim算法?

    从任意一个顶点开始,寻找与当前点最近的点,将两顶点的边加入到树中,构造出权值最小的生成树。

    详细来说:

    1.将图的所有点放到集合V内,从中选出任意一点作为点集U的起始点{v1}

    2.寻找V—U中与U中的点可连接的权值最小的点,将点加入U中,从V—U中删去(注意此时不能形成环)

    (实际算法中会引入一个辅助数组,记录从U到V—U的最小代价的边。所以这个辅助数组是实时更新的,例如:此时U{v1,v3},那么在v3寻找关连边的点时,碰到了与v1也可以关联的点,并且v3与该点的权值小于v1,那么更新辅助数组)

    3.重复2操作,直到V—U中的点为空,那么U中的点构成的树就是最小生成树

    什么是Kruskal算法?

    其实它也是构成最小生成树的算法,但是和Prim不同的是,Prim是根据点求出最小生成树,而Kruskal是根据边求出最小生成树。所以在边多的情况下,尽量不用Kruskal算法。

    详细来说:

    1.先将所有边按照权值由大到小进行排列

    2.按照顺序选择边,如果该边的两个节点不属于同一个集合,那就将它合并,如果属于同一个集合,就舍弃此边,再寻找下一边,直到所有的节点都属于同一个集合。

    那么这里发现一个问题,我们要如何将节点合并呢?

    这里就出现了一个并查集方法。

    什么是并查集?

    1.查询元素a与b是否处于同一个集合内

    2.合并元素ab为一组

    并查集结构用树来实现,如下图,当我们要看两个元素是否相等,那么只需要看它们的根节点是否相等,如果相等就属于同一集合。而合并时只需要将两个根节点相连就可以。

    简单的并查集算法会发现有一个巨大的缺点:极有可能退化成线性结构

    那么这时候就需要用“路径压缩”和“按秩合并”阻止它的退化

    什么叫路径压缩?

    将原本与根节点间接相连的点变为与根节点直接相连,如下图

    什么叫按秩合并(unit)?

    对于每一棵树,记录它的高度。每次合并树时,将矮的树挂在高的树下

    喷泉问题(一):

    作法:圆的内切正方形的边长为草坪的宽

    喷泉问题(二):

    作法:1.舍去半径小于草坪宽二分之一的圆,

               2.记录其他圆形成的矩形边界,排序符合的矩形

               3.判断第一个矩形的左边界是否大于零,大于零则不存在符合喷泉装置将草坪润湿

               4.遍历矩形右边界,直到右边界大于矩形长度,结束遍历,输出count值

    会场安排问题:

    作法:1.vector存下所有活动,将活动按结束时间的近远进行排序

               2.变量a保存vector的大小。

               3.看第一个活动结束时间是否大于其他活动的开始时间,如果大于某一活动,a减1,否则查看该活动的结束时间是否大于其他活动的开始时间(如果上一个活动在t时间内结束,那么下一个活动应该在t+1时间开始)

    过河问题:

    作法:1.当N==1或N==2,直接过河

               2.当N==3,最快与次快先过河,最快的拿着手电筒返回,再与最慢的一起过河

               3.当N>=4,a[0]为最快的人过河时间,a[1]为次快,a[n-1]为最慢的人过河,a[n-2]为次慢。通过N=3,4,归纳总结可知,过河时间存在两个方案

                方案一:a[0]与a[n-1]先过河,a[0]返回再与a[n-2]过河

                方案二:a[0]与a[1]先过河,a[0]返回,a[n-1]与a[n-2]过河,a[1]返回,a[0]与a[1]过河

                过河时间的方案的差异只与a[0],a[1],a[n-2]有关,当a[0]+a[n-2]-2a[1]>0时选择方案一,小于0选择方案二,每执行一次就减少两人,直到人小于4为止

    01背包问题:

    作法:将物品价值最大的先放入背包


    动态规划(大事化小)

    Q:动态规划的特征是什么?

    A:最优子结构、无后效性

          最优子结构:当前的最优状态可以由某个或某些状态直接得到

          无后效性:不管之前这个状态是如何得到的(比如迷宫问题,我们在记录当前路线的时候会影响到下一步路线的选择,这就是有后效性。os:搜索解决迷宫问题,搜索:每个阶段的最优状态都是由之前所有状态组合得到的。)

    动态规划的实质:

    1.分析问题,构造状态转移方程(通过最优子结构推导得出),注意边界问题

    2.以空间时间(什么是空间复杂性?支持计算所要用到的存储状态最多有多少

                                什么是时间复杂性?从初始状态到最终状态走了多少步)

    动态规划的解题步骤:

    1.确定子问题。(确定哪些变量随着问题规模的变小而变小)

    2.确定状态。(给子问题限定状态)

    3.推导出状态转移方程(根据子问题进行推导)

    4.确定边界

    5.确定实现方式

    6.确定优化方法(有时候会发现当执行到步骤5时就会返回步骤1继续执行,中间就会有很多重复部分,所以这时候就要采用:降维问题、优先队列、四边形不等式优化等)

    相关题目:

    有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。要求用程序来求出一共有多少种走法。

        1.假设只差最后一步就可以踏上第10级台阶,那么此时有两种方法,一个是站在第九级台阶往上走一步,另一个是站在第八级台阶往上走两步。

        2.假设走到九级有X种方法,走到八级有Y种方法,那么走到十级就是X+Y,所以这里可以得出递推方程:F(n)=F(n-1)+F(n-2)

        其实当我们推导出一个递推的方程F(n)=F(n-1)+F(n-2),如果直接用递推方式去解决,那么会存在很多重复的计算(当我们求F(n),要得到F(n-1),F(n-2)的值,要得到F(n-1),就要得到F(n-2),F(n-3)的值,可以看出F(n-2)计算了两次)。

        如果我们将F(n-1),F(n-2)存储起来,那么求解F(n)就只需要一步加法,此时时间复杂性降低,空间复杂性增加,这就叫做空间换时间。(这就叫做“备忘录算法”,备忘录算法保留所有子状态,它与动态规划的最大的不同就是它是“自顶向下”,动态规划是“自底向上”)

        再思考一下,能不能把空间复杂性缩小,那么我们自底向上,用迭代方式求出结果,台阶的走法数量由前两个台阶数量相加而成。所以我们根本不需要把所有的子状态都记录,只需要记录当前状态的前两个状态,就可以求出当前状态。这就是动态规划的实现

    最长公共子序列问题(LCS):

    解题思路:

    设A=“a0,a1.....am-1”,B="b0,b1...bn-1",Z="z0,z1...zk-1",Z为AB的最长公共子数列

    1.当am-1==bn-1时,则查找"a0,a1...am-2"与"b0,b1...bn-2"的最长公共子序列

    2.当am-1!=bn-1时,则在"a0,a1,....am-2"与"b0,b1..bn-1" 和 "a0,a1,....am-1"与"b0,b1..bn-2"中找到最长的公共子序列

    最长递增子序列问题(LIS):

    解题思路:

    1.因为是查找子序列而不是子串,所以递增序列不需要连续。

    2.外层遍历给定数组,内层遍历外层 i之前的数

        那么我们需要判断 a[ j ] < a[ i ] (以及Dp( i ) < Dp( j ) + 1),就可以给子序列的长度加1,所以得出状态转移方程为 Dp( i ) = Dp( j ) + 1


    优化上面的算法:

        将数一个一个插入队列中,如果发现当前数大于队尾数,那么就插在队尾,反之就用二分法查找大于当前数的最小值的位置,替换为当前数。

    01背包问题:

    解题思路:

    设B(i)为背包价值,W(i)为物品重量,V[i]为物品价值,capacity为背包可以放的最大容量

    1.物品有放和不放两种状态,那么如何判断放进去的东西能使利益最大化呢?

    2.当背包当前容量比物品重量还小时,不能再放进东西,这时背包的价值与前面B(i-1)价值相等

    3.当背包容量可以再放进物品,但装了也不一定达到当前的最优价值,所以在装与不装之间选择最优的一个,

    装进物品:

        就是取{w1,w2,w3....wi-1}的物品,装入体积为当前背包剩余容量减去要装进的物品wi容量,所得到的最大值再加上要wi的价值。

    不装入:

        就是取{w1,w2,w3....wi-1,wi}的物品,装入当前背包容量,所得的最大价值

    从上面两种找出最优价值即可,所以装不装只第i-1个物品有关。

    完全背包问题:

    解题思路:

    1.这个时候和01背包就不一样了,01背包是有取或者不取的策略,而这里则是取0种、取1种...等策略

    2.解题思路与01背包略微相似

       但是就是在背包容量可以放下东西时不同,这时候我们也需要在装与不装之间选择

    相关文章

      网友评论

        本文标题:(3更)算法总结

        本文链接:https://www.haomeiwen.com/subject/kpbwhftx.html