Leetcode dp问题汇总

面试题47. 礼物的最大价值

概述:在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定棋盘及其上面的礼物的价值,求最大价值。
思路:刚开始爆搜去了,果断给我T了,把数据缓存下来就a了,

int row,col;
    int map1[201][201];
    int maxValue(vector<vector<int>>& grid) {
     row=grid.size();
     if(!row) return 0;
     col=grid[0].size();
      return dfs(0,0,grid);
    }
    int dfs(int x,int y,vector<vector<int>>& grid){
        if(x>=row||y>=col) return 0;
        if(map1[x][y]>0) return map1[x][y];
        int a=dfs(x+1,y,grid),b=dfs(x,y+1,grid);
         map1[x][y]=grid[x][y]+max(a,b);
         return map1[x][y];
    }

打开题解一看,都是dp,,,
这是二维dp,用一个二维数组保存状态,dp方程dp[i][j]=max(dp[i-1][j],dp[i][j-1])+grid[i][j]
初始条件是0行0列的值,因为他是往右往下跑的。

    int row,col;
    int map1[201][201];
    int maxValue(vector<vector<int>>& grid) {
     row=grid.size();  if(!row) return 0;
     col=grid[0].size();
     int dp[201][201];
     dp[0][0]=grid[0][0];
     for(int i=1;i<col;i++) dp[0][i]=dp[0][i-1]+grid[0][i];
     for(int i=1;i<row;i++)  dp[i][0]=dp[i-1][0]+grid[i][0];
     for(int i=1;i<row;i++)
         for(int j=1;j<col;j++)
             dp[i][j]=max(dp[i-1][j],dp[i][j-1])+grid[i][j];
     return dp[row-1][col-1];
    }

可以优化成一维的

    int dp[201];
    int maxValue(vector<vector<int>>& grid) {
       int row=grid.size();
       int col=grid[0].size();
       for(int i=0;i<row;i++)
           for(int j=0;j<col;j++)
               dp[j+1]=max(dp[j],dp[j+1])+grid[i][j];
      return dp[col];
    }

264. 丑数 II

概述:按顺序找出前1670个丑数,丑数就是只包含质因数 2, 3, 5 的正整数。
思路:这道题因为下一个丑数可由之前丑数计算出来,当前状态由之前状态得出,满足无后效性,也算是dp。
采用三指针做法,计算丑数时是选取三个里最小的那一个,然后将这个指针后移一位。

   int nthUglyNumber(int n) {
       double res[1693];
        int p2=0,p3=0,p5=0;
        res[0]=1;
     for(int i=1;i<1691;i++){
          res[i]=min(2*res[p2],min(3*res[p3],5*res[p5]));
          if(res[i]==2*res[p2]) p2++;
          if(res[i]==3*res[p3]) p3++;
          if(res[i]==5*res[p5]) p5++;
     }
     return (int)res[n-1];
    }

338. 比特位计数

概述:0-num中每一个数字的二进制表示1的个数,O(n)的复杂度
思路:动态规划的思想,当num为奇数时候,num-1是偶数,1的个数就是num-1中1的个数加1,
当num为偶数时候,num-1为奇数,num不过是 num/2左移一位(可以理解为末尾加了个0),而1的个数没有发生改变。

    vector<int> countBits(int num) {
        vector<int>res;
        /*for(int i=0;i<=num;i++){ //我的暴力代码  果断tttt
            int cnt=0;
            while(i){
                if(i&1==1) cnt++;
                i>>1;
            }
            res.push_back(cnt);
        }
        */
        res.push_back(0);
         for(int i=1;i<=num;i++){
             int cnt=0;;
             if(i&1) cnt=res[i-1]+1;
              else cnt=res[i/2];
              res.push_back(cnt);
         }
/*
      int[] ans = new int[num + 1]; //官方题解里的最低有效位的方法,比我的写起来更简洁一些,
      for (int i = 1; i <= num; ++i)
        ans[i] = ans[i >> 1] + (i & 1);
*/
        return res; 
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容