• 最近一些动态规划的题型


    1.硬币问题 377. 组合总和 Ⅳ

    public int ways(int []nums,int target){
            int[]dp=new int[target+1];
            //dp[i]表示和为i有多少种组合
            dp[0]=1;
            for(int i=0;i<=target;i++)
                for(int n:nums){
                    if(n+i<=target)
                        dp[n+i]+=dp[i];
                }
            return dp[target];
        }
    简单递归
        int count(int[]nums,int sum,int tar){
            int res=0;
            if(sum<tar){
                for(int i:nums)
                    res+=count(nums,sum+i,tar);
            }else if(sum==tar)
                  return 1;
            else
                return 0;
            return res;
        }
    View Code

    2.LCS

    int lcs(String a,String b){
            int lena=a.length(),lenb=b.length();
            int [][]dp=new int[lena+1][lenb+1];
            //dp[i][j]表示a的前i个和b的前j个的LCS
            for(int i=1;i<=lena;i++)
                for(int j=1;j<=lenb;j++)
                    if(a.charAt(i-1)==b.charAt(j-1))
                        dp[i][j]=dp[i-1][j-1]+1;
                    else
                        dp[i][j]=Math.max(dp[i][j-1], dp[i-1][j]);
            return dp[lena][lenb];
        }

    3.0-1背包

        public int ways(int c){
            int packets=w.length;
            int [][]dp=new int[packets+1][c+1];
            for(int i=1;i<=packets;i++)
                for(int j=0;j<=c;j++){
                    if(j==0)
                        dp[i][j]=0;
                    else if(j>=w[i-1]){
                        dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-w[i-1]]+p[i-1]);
                    }else
                        dp[i][j]=dp[i-1][j];
                }
            return dp[packets][c];
        }

    空间优化后:

        public int ways2(int c){
            int packets=w.length;
            int []dp=new int[c+1];
            for(int i=1;i<=packets;i++)
                for(int j=c;j>=0;j--)
                    if(j>=w[i-1])
                        dp[j]=Math.max(dp[j], dp[j-w[i-1]]+p[i-1]);
            return dp[c];
        }

    简单递归

        public int solve(int i,int n,int j,int max){
            if(i<n){
                if(j>=w[i]){
                    return Math.max(solve(i+1,n,j-w[i],max+p[i]),solve(i+1,n,j,max));
                }else{
                    return solve(i+1,n,j,max);
                }    
            }else
                return max;
        }
    View Code

    3.多重背包

        public int packetK(int c){
            int [][]dp=new int[w.length+1][c+1];
            for(int i=1;i<=w.length;i++)
                for(int j=0;j<=c;j++)
                    if(j==0)
                        dp[i][j]=0;
                    else if(j<w[i-1])
                        dp[i][j]=dp[i-1][j];
                    else{
                        for(int k=1;k*w[i-1]<=j;k++){
                            int tmp=Math.max(dp[i-1][j], dp[i-1][j-k*w[i-1]]+k*p[i-1]);
                            dp[i][j]=dp[i][j]<tmp?tmp:dp[i][j];
                        }
                    }
            return dp[w.length][c];
        }

    4.最长非降序子序列 类似 300. 最长上升子序列

    //最长非降序子数列
        public int MaxUnDESCSub(int []nums){
            int []dp=new int[nums.length];
            //dp[i]为0..i不降序的最大字串长度
            Arrays.fill(dp, 1);
            for(int i=1;i<nums.length;i++){
                for(int j=0;j<i;j++){
                    if(nums[i]>=nums[j]&&dp[i]<=dp[j])
                        dp[i]=dp[j]+1;
                }
            }
            Arrays.sort(dp);
            return dp[nums.length-1];
        }

    5.爬台阶

        public int ways(int n){
            int []dp=new int[n+1];
            dp[1]=1;dp[2]=1;
            for(int i=3;i<=n;i++)
                dp[i]=dp[i-1]+dp[i-2];
            return dp[n];    
        }

    6.平衡字串(前缀思想 

    public int maxBlancedSub(String s){
            /*
             *前缀和思想 连续性
             *dp[i]表示前i个数 */
            int len=s.length();
            int []dp=new int[len+1];
            for(int i=1;i<=len;i++)
                if(s.charAt(i-1)=='0')
                    dp[i]=dp[i-1]-1;
                else
                    dp[i]=dp[i-1]+1;
            HashMap<Integer,Integer>map=new HashMap<>();
            int max=0,begin=0;
            for(int i=1;i<=len;i++){
                if(map.containsKey(dp[i]))
                    begin=map.get(dp[i]);
                else
                    map.put(dp[i], i);
                if(dp[i]==dp[begin]&&i-begin>max)
                    max=i-begin;
            }
            return max;
        }

     7.图论问题 leetcode787

     public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
              int [][]dp=new int[n][k+1];
              int [][]f=new int[n][n];
              for(int i=0;i<n;i++){
                  Arrays.fill(dp[i], Integer.MAX_VALUE);
                  Arrays.fill(f[i], -1);
                  f[i][i]=0;
              }
              for(int i=0;i<flights.length;i++)
                  f[flights[i][0]][flights[i][1]]=flights[i][2];
              /*
               * dp[i][j] 到达i站 且经过站数为j 的最小cost*/
              for(int j=0;j<=k;j++){
                  for(int i=0;i<n;i++){
                      if(i==src)
                          dp[i][j]=0;
                      else if(j==0&&f[src][i]>=0)
                          dp[i][j]=f[src][i];
                      else if(j>0){
                          for(int m=0;m<n;m++)
                              if(m!=i&&f[m][i]>0&&dp[m][j-1]!=Integer.MAX_VALUE)
                                  dp[i][j]=Math.min(dp[m][j-1]+f[m][i], dp[i][j]);
                      }
                  }
              }
              Arrays.sort(dp[dst]);
              if(dp[dst][0]!=Integer.MAX_VALUE)
                  return dp[dst][0];
              return -1;
          }

    8.不同种类二叉搜索树

        public int numTrees(int n) {
           int []dp=new int[n+1];
           for(int i=1;i<=n;i++){
               if(i==1||i==2)
                   dp[i]=i;
               else{
                   for(int j=1;j<=i;j++)
                       if(j>1&&j<i)//有左子树和右子树
                           dp[i]+=dp[j-1]*dp[i-j];
                       else if(j==1)//只有右子树
                           dp[i]+=dp[i-j];
                       else
                           dp[i]+=dp[j-1];
               }
           }
           return dp[n];
        }
  • 相关阅读:
    怎么使用git来管理项目版本?
    《我的四季》 张浩
    [代码片段]读取BMP文件(二)
    [代码片段]读取BMP文件
    《构建之法》阅读笔记02
    二维数组
    学习进度二
    《构建之法》阅读笔记01
    数组
    软件工程第一周开课博客
  • 原文地址:https://www.cnblogs.com/yuelien/p/10492393.html
Copyright © 2020-2023  润新知