简单易懂动态规划算法

什么是动态规划

把原问题分解成若干个相对简单的子问题,然后逐步解决子问题从而解决复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。

基本思想

若要解出一个相对复杂的问题,我们需要解出其子问题,再合并子问题从而得到原问题的解。

问题特征

最优子结构:当原问题最优解包含了其子问题的最优解时,称该问题具有最优子结构。

重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。

分治与动态规划

共同点:二者都要求原问题具有最优子结构性质,都是将原问题分而治之,分解成若干个规模较小(小到很容易解决的程序)的子问题.然后将子问题的解合并,形成原问题的解.

不同点:分治法将分解后的子问题看成相互独立的,通过用递归来做。

     动态规划将分解后的子问题理解为相互间有联系,有重叠部分,需要记忆,通常用迭代来做。

递归和迭代定义

相同点:

递归和迭代都是循环的一种。

不同点:

      1、程序结构不同

递归是重复调用函数自身实现循环。

迭代是函数内某段代码实现循环。

其中,迭代与普通循环的区别是:迭代时,循环代码中参与运算的变量同时是保存结果的变量,当前保存的结果作为下一次循环计算的初始值。

      2、算法结束方式不同

 递归循环中,遇到满足终止条件的情况时逐层返回来结束。

迭代则使用计数器结束循环。

  当然很多情况都是多种循环混合采用,这要根据具体需求。

      3、效率不同

在循环的次数较大的时候,迭代的效率明显高于递归。

动态规划的解决步骤

  1. 判断题意是否为找出一个问题的最优解
  2. 从上往下分析问题,大问题可以分解成子问题,子问题还有更小的子问题
  3. 从下往上分析问题,找出这些问题之间的关联(状态转移方程)
  4. 讨论底层的边界问题
  5. 解决问题(通常使用数组进行迭代求出最优解)

 

例题:找最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"

输出: "bab"

注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"

输出: "bb"

 

/*使用动态规划
     * 步骤1:找到状态转移函数
     * 步骤2:找到底界问题两种情况(第一种是最中间是一个字母,第二种是最中间相邻相同)
     * 步骤3:解决问题
     */    
class Solution {
    public String longestPalindrome(String s) {
        if(s.equals(""))
    {
        return "";
    }
    String temp=String.valueOf(s.charAt(0));
    //第一种
    for(int i=0;i<s.length();i++)
    {
         for(int j_min=i-1,j_max=i+1;j_min>=0&&j_max<s.length();j_min--,j_max++)
         {
             if(String.valueOf(s.charAt(j_min)).equals(String.valueOf(s.charAt(j_max))))
             {
                 if(temp.length()<(j_max-j_min+1))
                 {
                     temp=s.substring(j_min, j_max+1);
                 }
                
             } else break;
          }
        }
    //第二种
    for(int i=0,j=1;i<s.length()&&j<s.length();i++,j++)
    {
         for(int j_min=i,j_max=j;j_min>=0&&j_max<s.length();j_min--,j_max++)
         {
             if(String.valueOf(s.charAt(j_min)).equals(String.valueOf(s.charAt(j_max))))
             {
                 if(temp.length()<(j_max-j_min+1))
                 {
                     temp=s.substring(j_min, j_max+1);
                 }
                
             } else break;
          }
        }
              return temp;
        
    }
}

 

 

 

posted @ 2019-04-10 21:23  fish大叔  阅读(622)  评论(0编辑  收藏  举报