代码随想录——动态规划习题合集(一)

509. 斐波那契数

    int fib(int n) {
        if(n==1) return 1;
        int aa[40];
        aa[0]=0;aa[1]=1;
        for(int i=2;i<=n;i++){
            aa[i]=aa[i-1]+aa[i-2];
        }
        return aa[n];
    }

 70. 爬楼梯

 int climbStairs(int n) {
        int f[50];
        f[1]=1;
        f[2]=2;
        for(int i=3;i<=n;i++){
            f[i]=f[i-1]+f[i-2];
        }
        return f[n];
    }

 746. 使用最小花费爬楼梯

int minCostClimbingStairs(vector<int>& cost) {
            int f[1010];
            f[0]=0;
            f[1]=0;
            for(int i=2;i<=cost.size();i++){
                f[i]=min(f[i-1]+cost[i-1],f[i-2]+cost[i-2]);
            }
            return  f[cost.size()];
    }

 62. 不同路径

二维做法

int uniquePaths(int m, int n) {
        int a[m][n];
        for(int i=0;i<m;i++) a[i][0]=1;
        for(int i=0;i<n;i++) a[0][i]=1;
        
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i&&j) a[i][j]=a[i-1][j]+a[i][j-1];
            }
        }

        // for(int i=0;i<m;i++){
        //     for(int j=0;j<n;j++){
        //         cout<<a[i][j]<<" ";
        //     }cout<<endl;
        // }

        return a[m-1][n-1];
    }

一维做法

    int uniquePaths(int m, int n) {
        int a[n];
        for(int i=0;i<n;i++) a[i]=1;
        
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i&&j) a[j]=a[j]+a[j-1];
            }
        }
        return a[n-1];
    }

 63. 不同路径 II

 二维做法

 int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if(obstacleGrid[0][0]==1) return 0;
        int n=obstacleGrid.size(),m=obstacleGrid[0].size();
        int f[n][m];
        memset(f,0,sizeof(f));
        for(int i=0;i<n;i++){
            if(obstacleGrid[i][0]==1) break;
            f[i][0]=1;
        }
        for(int i=0;i<m;i++){
            if(obstacleGrid[0][i]==1) break;
            f[0][i]=1;
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(obstacleGrid[i][j]==1) f[i][j]=0;
                if(obstacleGrid[i][j]!=1&&i&&j) f[i][j]=f[i-1][j]+f[i][j-1];
            }
        }
        return f[n-1][m-1];
    }

 一维做法

 int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if(obstacleGrid[0][0]==1) return 0;
        int n=obstacleGrid.size(),m=obstacleGrid[0].size();
        int f[m];
        memset(f,0,sizeof(f));
        for(int i=0;i<m;i++){
            if(obstacleGrid[0][i]==1) break;
            f[i]=1;
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(obstacleGrid[i][j]==1) f[j]=0;
                if(obstacleGrid[i][j]!=1&&i&&j) f[j]=f[j]+f[j-1];
            }
        }
        return f[m-1];
    }

 343. 整数拆分

 数学方法:3尽可能多2最多两个。

   int integerBreak(int n) {
        if(n<=3) return n-1;
        int p=1;
        while(n>=5) n-=3,p*=3;
        return p*n;
    }

dp:

 int integerBreak(int n) {
      int f[100];
      memset(f,0,sizeof(f));
      f[1]=1;
      f[2]=1;
      f[3]=2;
      for(int i=3;i<=n;i++){
          for(int j=2;j<=i;j++){
              f[i]=max(f[i],max((i-j)*j,f[i-j]*j));
          }
      }
      return f[n];
    }

96. 不同的二叉搜索树

  递推方程:dp[j]=sum(f[i-j-1]*f[j])

 int numTrees(int n) {
        int f[n+10];
        memset(f,0,sizeof(f));
       f[0]=1;f[1]=1;f[2]=2,f[3]=5;
       for(int i=4;i<=n;i++){
           for(int j=0;j<i;j++){
               f[i]+=f[i-j-1]*f[j];
           }
       }
       return f[n];
    }

416. 分割等和子集

 递推方程:dp[i][j]=max(dp[i-1][j],dp[i][j-nums[i]+nums[i]]

  bool canPartition(vector<int>& nums) {
        int sum=0;
        for(int i=0;i<nums.size();i++) sum+=nums[i];
        if(sum%2==1) return false;

        int f[sum/2+1];
        memset(f,0,sizeof(f));
        for(int i=0;i<nums.size();i++) {
            for(int j=sum/2;j>=nums[i];j--){
                f[j]=max(f[j],f[j-nums[i]]+nums[i]);
            }
        }
        if(f[sum/2]==sum/2) return 1;
        else return 0;
    }

 1049. 最后一块石头的重量 IId

 递推方程:dp[i][j]=max(dp[i-1][j],dp[i][j-stones[i]+stones[i]]

int lastStoneWeightII(vector<int>& stones) {
      int sum=0;
      for(int i=0;i<stones.size();i++) sum+=stones[i];
      int tar=sum/2;
      int f[tar+10];
      memset(f,0,sizeof(f));
      for(int i=0;i<stones.size();i++){
          for(int j=tar;j>=stones[i];j--){
              f[j]=max(f[j],f[j-stones[i]]+stones[i]);
          }
      }
      return sum-f[tar]-f[tar];
    }

 494. 目标和

递推方程:dp[i][j]=dp[i-1][j]+dp[i][j-nums[i]];

 int res=0;int aa=0;
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0;
        for(int i=0;i<nums.size();i++) sum+=nums[i];
        if((target+sum)%2==1||abs(target)>sum) return 0;
        int  xx=(target+sum)/2;
        vector<int>f(xx+1,0);
        f[0]=1;
        for(int i=0;i<nums.size();i++)
            for(int j=xx;j>=nums[i];j--) f[j]+=f[j-nums[i]];
        
      return f[xx];
    }

 474. 一和零d

 递推方程:dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-zero][k-one]+1)

 三维

 int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> nums;
        for(int i=0;i<strs.size();i++){
            int one=0,zero=0;
            vector<int> temp;
            for(int j=0;j<strs[i].size();j++){
                if(strs[i][j]=='1') one++;
                else zero++;
            }
            temp.push_back(zero);temp.push_back(one);
            nums.push_back(temp);
        }
        vector<int> xx;
        xx.push_back(0);xx.push_back(0);
        nums.insert(nums.begin(),xx);
        int dp[nums.size()+1][m+1][n+1];
        memset(dp,0,sizeof(dp));
        
        for(int i=1;i<nums.size();i++){
            int zero=nums[i][0],one=nums[i][1];
            for(int j=0;j<=m;j++){
                for(int k=0;k<=n;k++){
                    dp[i][j][k]=dp[i-1][j][k];
                    if(k) dp[i][j][k]=max(dp[i][j][k],dp[i][j][k-1]);
                    if(j) dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k]);
                    if(j>=zero&&k>=one)
                    dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-zero][k-one]+1);
                }
            }
        }   
        return dp[nums.size()-1][m][n];
    }   

二维优化:

 int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> nums;
        for(int i=0;i<strs.size();i++){
            int one=0,zero=0;
            vector<int> temp;
            for(int j=0;j<strs[i].size();j++){
                if(strs[i][j]=='1') one++;
                else zero++;
            }
            temp.push_back(zero);temp.push_back(one);
            nums.push_back(temp);
        }
        vector<int> xx;
        xx.push_back(0);xx.push_back(0);
        nums.insert(nums.begin(),xx);
        int dp[m+1][n+1];
        memset(dp,0,sizeof(dp));
        
        for(int i=1;i<nums.size();i++){
            int zero=nums[i][0],one=nums[i][1];
            for(int j=m;j>=zero;j--){
                for(int k=n;k>=one;k--){
                    if(k) dp[j][k]=max(dp[j][k],dp[j][k-1]);
                    if(j) dp[j][k]=max(dp[j][k],dp[j-1][k]);
                    if(j>=zero&&k>=one)
                    dp[j][k]=max(dp[j][k],dp[j-zero][k-one]+1);
                }
            }
        }   
        return dp[m][n];
    }   

 518. 零钱兑换 II

递推方程:dp[i][j]+=dp[i-1][j-nums[i]*k]//k是个数 

二维写法 

 int change(int amount, vector<int>& nums) {
        nums.insert(nums.begin(),0);
        int f[nums.size()+1][amount+1];
        memset(f,0,sizeof(f));
       f[0][0]=1;
        for(int i=1;i<nums.size();i++){
            for(int j=0;j<=amount;j++){
               // f[i][j]=f[i-1][j];
                for(int k=0;k*nums[i]<=j;k++){
                    f[i][j]+=f[i-1][j-nums[i]*k];
                }
            }
        }
        return f[nums.size()-1][amount];
    }

 一维写法

 int change(int amount, vector<int>& nums) {
        nums.insert(nums.begin(),0);
        int f[amount+1];
        memset(f,0,sizeof(f));
       f[0]=1;
        for(int i=1;i<nums.size();i++){
            for(int j=amount;j>=0;j--){
                for(int k=1;k*nums[i]<=j;k++){
                    f[j]+=f[j-nums[i]*k];
                }
            }
        }
        return f[amount];
    }

 377. 组合总和 Ⅳ

 int combinationSum4(vector<int>& nums, int target) {
        nums.insert(nums.begin(),0);
       int f[target+1];
        memset(f,0,sizeof(f));
        f[0]=1;
        
        for(int i=0;i<=target;i++){
            for(int j=1;j<nums.size();j++){
              if(i>=nums[j]&&f[i]<INT_MAX-f[i-nums[j]])  f[i]+=f[i-nums[j]];
            }
        }
       return f[target];
    }

322. 零钱兑换

 int coinChange(vector<int>& coins, int amount) {
        int f[amount+1];
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        coins.insert(coins.begin(),0);
        for(int i=1;i<coins.size();i++){
            for(int j=coins[i];j<=amount;j++){
                if(j>=coins[i]) f[j]=min(f[j],f[j-coins[i]]+1);
            }
        }
        if(f[amount]>=0x3f3f3f3f/2) return -1;
        return f[amount];
    }

 279. 完全平方数

int numSquares(int n) {
        vector<int> nums;
        for(int i=0;i*i<=n;i++)   nums.push_back(i*i);
        
        int f[n+1];
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        for(int i=1;i<nums.size();i++){
            for(int j=nums[i];j<=n;j++){
                if(j>=nums[i]) f[j]=min(f[j],f[j-nums[i]]+1);
            }
        }
        return f[n];
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值