目录
1.动态规划问题分类
2.线性DP
        一维数组
        二维坐标系
        LIS(最长上升子序列)
        LCS(最长公共子序列)
        01背包
        完全背包
        多重背包

1.动态规划问题分类

2.线性DP

2.1一维数组

思路:
一个连续子数组一定要以一个数作为结尾,那么我们可以将状态定义成如下:

dp[i]:表示以 nums[i] 结尾的连续子数组的最大和。

那么想得到dp[i],nums[i]我们是一定会选取的,根据dp[i-1]的大小我们分为两种情况

dp[i-1]大于0的话:dp[i]=dp[i-1]+nums[i]
dp[i-1]小于0的话:dp[i]=nums[i]
(加上dp[i-1]反而还没有一定会选取的nums[i]大)

C++代码:

class Solution {public:int maxSubArray(vector<int>& nums) {if(nums.empty())return 0;vector<int> dp(nums.size(),0);dp[0]=nums[0];int max=nums[0];for(int i=1;i<nums.size();i++){if(dp[i-1]>=0){dp[i]=dp[i-1]+nums[i];if(dp[i]>max)max=dp[i];}else{dp[i]=nums[i];if(dp[i]>max)max=dp[i];}}return max;}
};


思路:

我们定义dp[i]为偷盗至第i个房子时,所能获取的最大利益。那我们可以想到,由于不可以在相邻的房屋闯入,所以 至i房屋可盗窃的最大值,要么就是至 i-1 房屋可盗窃的最大值,要么就是至 i-2 房屋可盗窃的最大值加上当前房屋的值,二者之间取最大值。即:

dp[i] = max(dp[i-2]+nums[i], dp[i-1])

这里要注意对于第二间房间偷盗的最大金额为前两间房间所有的金额的最大值

C++代码:

class Solution{public:int rob(vector<int>& nums) {if(nums.empty())return 0;if(nums.size()>=2)nums[1]=max(nums[0],nums[1]);for(int i=2;i<nums.size();i++)nums[i]=max(nums[i]+nums[i-2],nums[i-1]);return nums[nums.size()-1];}
};

2.2二维数组

思路:

我们定义d[i][j]:

dp[i][j] : 表示包含第i行j列元素的最小路径和

无论最后的路径是哪一条,它一定要经过最顶上的元素,即[0,0]。所以我们需要对dp[0][0]进行初始化。

dp[0][0] = [0][0]位置所在的元素值

每一行最左边的元素只能从自己头顶而来: dp[i][j]=dp[i-1][j]+triangle[i][j];
每一行最右边的元素只能从自己左上角而来: dp[i][j]=dp[i-1][j-1]+triangle[i][j];
其余的元素是从左边或者头顶元素两种途径而言(既然是要求最小,那么取两种途径的最小值): dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+triangle[i][j];

C++代码:

class Solution {public:int minimumTotal(vector<vector<int>>& triangle) {int size=triangle.size();int dp[size][size];memset(dp,0,sizeof(dp));dp[0][0]=triangle[0][0];for(int i=1;i<size;i++){for(int j=0;j<=i;j++){if(j==0)dp[i][j]=dp[i-1][j]+triangle[i][j];else if(j==i)dp[i][j]=dp[i-1][j-1]+triangle[i][j];elsedp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+triangle[i][j];}}int min=INT_MAX;for(int i=0;i<size;i++){if(min>dp[size-1][i])min=dp[size-1][i];}return  min;}
};

思路:
本题可以不使用任何额外的空间就能解答

我们先分析第一行,我们在第一行从左往右扫描,如果是0那么就有1种走法就把这个位置的元素变成1,如果有一个位置有障碍物,那么包含这个位置在内,障碍物后边元素的走法都是0。这可以用标志位在程序中实现,定义一个flag=0,如果找到一个障碍物后标志位置1。

我们没扫描元素之前,元素的0和1是代表有无障碍物,扫描之后代表的是这个位置有多少种走法

我们再分析第一列,同样的第一列只要有1个位置是障碍物,包含障碍物在内走法都是0

对于其他的,是障碍物,那么障碍物所在位置的走法一定是0,对于不是障碍物,那么走法是左边元素和上边元素的和(即使左边和上边的元素是障碍物也无所谓,因为障碍物的走法是0)

C++代码实现:

class Solution {public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m=obstacleGrid.size();int n=obstacleGrid[0].size();int flag=0;int f=0;if(obstacleGrid[0][0])return 0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(i==0&&j!=0&&obstacleGrid[i][j]==0&&flag==0)obstacleGrid[i][j]=1;else if(i==0&&j!=0&&obstacleGrid[i][j]==1){obstacleGrid[i][j]=0;flag=1;}else if(j==0&&obstacleGrid[i][j]==0&&f==0)obstacleGrid[i][j]=1;else if(j==0&&obstacleGrid[i][j]==1){obstacleGrid[i][j]=0;f=1;}else{if(obstacleGrid[i][j]==0&&i>0&&j>0)obstacleGrid[i][j]=obstacleGrid[i-1][j]+obstacleGrid[i][j-1];elseobstacleGrid[i][j]=0;        }}}return obstacleGrid[m-1][n-1];}
};

2.3LIS

本题我们可以按照w从小到大排序,w相同的按照h从大到小(这样整个问题就变成了求排序后h的最大增长子序列),再用动态规划求解

C++代码:

bool com(vector<int> &a,vector<int> &b){if(a[0]>b[0])return false;else if(a[0]<b[0])return true;else{if(a[1]<b[1])return false;else return true;}
}
class Solution {public:int maxEnvelopes(vector<vector<int>>& envelopes) {if(!envelopes.size()) return 0;sort(envelopes.begin(),envelopes.end(),com);vector<int> res(envelopes.size(),1);vector<int> vec;int max1=0;for(int i=0;i<envelopes.size();i++)vec.push_back(envelopes[i][1]);for(int i=0;i<vec.size();i++){for(int j=0;j<i;j++){if(vec[i]>vec[j])res[i]= max(res[i],res[j]+1);}if(max1<res[i])max1=res[i];}return max1;  }};

2.4LCS

子序列类型的问题,穷举出所有可能的结果都不容易,而动态规划算法做的就是穷举 + 剪枝,它俩天生一对儿。所以可以说只要涉及子序列问题,十有八九都需要动态规划来解决。

本题我们可以使用二维数组来做dp[i][j]的意思就是text1的前i个字符与text2的前j个字符的最大公共序列

因此可以得出:
现在对比的这两个字符不相同的,那么我们要取它的「要么是text1往前退一格,要么是text2往前退一格,两个的最大值」
dp[i + 1][j + 1] = Math.max(dp[i+1][j], dp[i][j+1]);

对比的两个字符相同,去找它们前面各退一格的值加1即可:dp[i+1][j+1] = dp[i][j] + 1;

class Solution {public:int longestCommonSubsequence(string text1, string text2) {int m=text1.size(),n=text2.size();   int dp[m+1][n+1];memset(dp,0,sizeof(dp));for (int i=1;i<=m;i++) {for (int j=1;j<=n;j++) {if (text1[i-1]==text2[j-1]) {dp[i][j]=dp[i-1][j-1]+1;} else {dp[i][j]=max(dp[i-1][j],dp[i][j-1]);}}}return dp[m][n];}
};

2.3 01背包

动态规划各类问题分析——LeetCode习题精讲相关推荐

  1. Java入门算法(动态规划篇2:01背包精讲)

    本专栏已参加蓄力计划,感谢读者支持❤ 往期文章 一. Java入门算法(贪心篇)丨蓄力计划 二. Java入门算法(暴力篇)丨蓄力计划 三. Java入门算法(排序篇)丨蓄力计划 四. Java入门算 ...

  2. 大学生数学竞赛习题精讲_陈兆斗

    大学生数学竞赛习题精讲_陈兆斗 链接: https://pan.baidu.com/s/1ctyZqmD-6VFgILBM0DiTcg 提取码: i76s 复制这段内容后打开百度网盘手机App,操作更 ...

  3. LeetCode 例题精讲 | 08 排列组合问题:回溯法的候选集合

    点击关注上方"五分钟学算法", 设为"置顶或星标",第一时间送达干货. 转自面向大象编程 本期例题:LeetCode 46 - Permutations[1]( ...

  4. LeetCode 例题精讲 | 05 双指针×链表问题:快慢指针

    点击关注上方"五分钟学算法", 设为"置顶或星标",第一时间送达干货. 转自面向大象编程 本期例题: LeetCode 876 - Middle of the ...

  5. l2-004 这是二叉搜索树吗?_LeetCode 例题精讲 | 11 二叉树转化为链表:二叉树遍历中的相邻结点...

    本期例题: LeetCode 98. Validate Binary Search Tree 验证二叉搜索树(Medium) LeetCode 426. Convert Binary Tree to ...

  6. 水稻微生物组时间序列分析精讲1-模式图与主坐标轴分析

    写在前面 上周五我们分享了3月底发表的的 <水稻微生物组时间序列分析>的文章,大家对其中图绘制过程比较感兴趣.一上午收到了超30条留言,累计收到41个小伙伴的留言求精讲. 我们也争取花时间 ...

  7. c++ 传智课件_初二物理《科学探究:液体的压强》微课精讲+知识点+课件教案习题...

    初中物理8-9年级微课精讲+课件教案下载 视频教学: 重点知识: 一.液体压强的特点 1.液体内部产生压强的原因:液体受重力且具有流动性. 2.测量:压强计(测量液体内部的压强) 压强计的构造: 压强 ...

  8. 「leetcode」最强回溯算法总结篇!历时21天、画了20张树形结构图、14道精选回溯题目精讲

    本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略.各个类型经典题目刷题顺序.思维导图,可以fork ...

  9. DayDayUp:大学英语六级考试历年真题答案规律分析、应试回答精讲、及六级改革历史之详细攻略

    DayDayUp:大学英语六级考试历年真题答案规律分析.应试回答精讲及六级改革历史之详细攻略 目录 大学英语六级考试历年真题规律分析 1.英六试题结构 2.英语六级改革历史

最新文章

  1. python处理大量excel数据-python如何批量处理excel数据?
  2. 如何快速解决虚拟机中的CentOS7无法上网的方式
  3. 【Linux部署】【elasticsearch-6.4.3 单机版】【不能以root用户运行es 及 max_map_count 问题解决】(含 安装包+分词插件 云盘资源)
  4. 从后端获取数据然后在页面处理技巧
  5. IOS之AutoLayout框架的使用
  6. Ch5302-金字塔【区间dp】
  7. .net中的硬盘操作(针对Windows )
  8. LeetCode 281. 锯齿迭代器(map+vector)
  9. 解决mysql ERROR 1045(28000)问题【忘记密码,修改配置文件,无密码登录mysql修改密码】
  10. 西瓜书《机器学习》线性模型 一元线性回归公式推导
  11. safari windows版本_iPhone 和 Windows 协作的五个技巧
  12. arduino图形编程——ardublock
  13. wsgiserver python 漏洞_python-简单测试wsgi
  14. python3库函数_python3的函数调用
  15. 浅谈逆向——从案例谈OD的使用(OD的使用2)
  16. Dex2Oat执行参数总结
  17. 复制瑞幸模式,出局的陆正耀再创业,要先开500家面馆
  18. input框不允许输入负数
  19. Oracle Database 10g for Windows安装
  20. vue-element-admin入坑之切换中文版

热门文章

  1. 【MCtalk活动推荐】IM快速搭建即时通讯实战
  2. 东莞首办工业机器人成果交流会听众爆满
  3. [译] 关于Angular的变更检测(Change Detection)你需要知道这些
  4. 关于mvc、mvp和mvvm的理解
  5. lucene、solr、nutch三者的关系
  6. 11gR2 RAC手动添加节点数据库实例
  7. linux,mac,unix 系统下cd 进入有空格的目录或者打开有空格的文件
  8. MapInfo之格式说明(转载)
  9. C 语言判断大端小端
  10. Redis 命令--Redis哈希(hash)