左 . 算法--- 前缀树/贪心策略/递归/ 动态规划专题



前缀树:



举例:  如图所示   路径上标的是字符串中单个字符   




升级 1(查找是否有特定字符串):

如果要查找"de"前缀的字符串,很好做到    但是查找是否有"de"字符串就不太好确定 (因为和"def"类似的结构是相同的)

所以   在刚才的基础上    在每个节点加上计数器 如果以此节点为末尾节点 则+1 





升级 2 ( 确定含有特定前缀的字符串个数 ):

就在每个节点处开辟另一个参数区域 用来记录有几个字符串经过  经过一次 则区域计数+1





代码:

   


    


   



删除时候需要注意:如果某个节点已经为0  则其子节点也就不要了~~直接赋值为null







贪心策略

给定几个字符串,将它们拼接起来构成最小的字符串(字典序):

贪心策略1 : 按照分部字典序去拼接----不一定整体是字典序最前的。

贪心策略2:  如果拼接起来是字典序最前的  -----则按照这个排下来。







分析贪心策略:必须具有传递性----这样上述条件才成立

如果是在数字类型题中 ,可以根据字符串最终还原成连接起来的数字形式。  

K进制    则  前面的a*k(b长度)+b----表示成整体连接之后的数字形式




证明可以得出:



再证明:

假设有a----b----     证明a放在前面一定是最好的选择  









贪心--分金条使代价最低:



思路: 类似于 霍夫曼树   最终统计的是   非叶子节点的总和




解决工具:  采用小根堆   每次取出其中最小的两个 类似于组建哈夫曼树  不断向上  

                   直到堆中只剩下一个元素   最终统计所有的求和

主要核心:  在于我们想去寻找两个尽可能大小相当的  所以堆这个结构刚刚好



代码:



总结:

当总共的代价由子代价 累加或者累乘  时 ,可能还会有对应的公式 ,则可能用哈夫曼编码的思路做出来。



贪心--做有限项目使利润最大化:



题意: 有一批项目 每个项目对应两个参数 一个cost(成本) 一个profit(利润)  

           最初给定一笔启动资金W   每次只能执行一个项目  (必须在资金以内的项目)    

           最多做K个项目   如何使最终获得的钱数最大~

思路:  小根堆---按照花费排(小根堆存放全部的项目)---取出未超过启动资金的花费项目

            ----再进入大根堆---按照利润排----(大根堆存放解锁的项目)

            不断的进行上述挑选--每次解锁一堆项目--从中拿出利润最大的进行---之后重复

         






代码:










贪心--在有限时间内使会议室内宣讲场次最多:




思路:

考虑几种可能的贪心策略: 1  开始时间早(然而结束时间超级晚)

                                         2  持续时间短(然而 影响前后两个宣讲场次)

                                         3  结束时间短的~~(为最可能的)



代码:










递归和动态规划:


   


求阶乘n!  :

递归和非递归写法:




汉诺塔问题:




时间复杂度为  2(n)-1  n次方






打印一个字符串的全部子序列,包括空字符串。

递归法:



原理:类似于二叉树  到叶子节点就开始打印






打印字符串的全排列:








母牛数量:


列举出前几项:




规律总结:









二维数组的最小路径和:


思路:

从(i,j)点出发到右下角点的最小路径和:

1  如果(i,j)就是 右下角点 则路径和  返回该点值 

2  如果已经到最后一行 则只能继续往右走  则该点值+右边点距离终点的最小路径和

3 如果已经到最后一列  则只能继续往下走  则该点值+ 下边点距离终点的最小路径和

4  如果是正常情况 可以向右 / 向下  则考察右端和下端具体最小路径和+ 该点值=最终最小路径和





此种方法复杂度较高:



由图中可以看出  重复状态出现次数太多---暴力递归



暴力递归改动态规划:


其实变成了从下往上 递归  

1  写出尝试版本(递归形式)

2 分析可变参数 分析哪几个参数可以代表返回值状态  可变参数几维 ---几维表

3 观察需要的终止状态--在表中点出--回到base  cases把完全不依赖的值设置好(如最后一行最后一列)

4  观察一个普遍位置 需要哪些位置  逆着回去 就是填表的顺序





给定数组和特定数字,是否能够累加求和为该数字?



思路:

先想递归:




代码:

两种选择中有一个为true即整体为true





从暴力递归转成动态规划:

特殊情况考虑: 数组中全部数字总和都<aim  直接返回false即可

考虑是否具有后效性  (与前面的选择无关)

考虑可变参数   数组固定数字固定 只有i和sum不固定

 画出dp图:最后一行是定的 由base case确定的


猜你喜欢

转载自blog.csdn.net/duoduo18up/article/details/80601021