Article directory
- Introductory Dynamic Programming:
-
- 70. Climb the stairs
- 746. Climb the stairs with minimum cost
- 198. Robbery
- 213. Robbery II
- 91. Decoding method
- 1646. Get the maximum value in the generated array
- 1043. Split an array to get maximum sum
- 139. Word splitting
- 1869. Which consecutive substring is longer?
- 724. Find the center index of an array
- 1277. Square submatrix whose statistics are all ones
Introductory Dynamic Programming:
Memory model search, optimize repeated calculation nodes (hash table is required to store status), and pay attention to boundary values to prevent recursion.
You can calculate backwards, starting from n -1 calculation, come up with the best plan every time for calculation
70. Climb the stairs
class Solution {
int dp[50];
public:
int climbStairs(int n) {
dp[0] = dp[1] =1;
for(int i=2;i<=n;i++)
{
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
剑指 Offer 10- II. 青蛙跳台阶问题
class Solution {
#define mod 1000000007
int f[107]; //表示跳上i级台阶的方案数
public:
int numWays(int n) {
f[0] = f[1] = 1;
for(int i=2;i<=n;i++)
{
f[i] = (f[i-1] + f[i-2])%mod; //递推思想 因为到达第n阶只有两种方法,一种是从n-1上一步,第二种是从n-2上走两步,故需要保存两种方法的方案即可
}
return f[n];
}
};
746. Climb the stairs with minimum cost
class Solution {
#define len 1001
int f[len];
public:
int minCostClimbingStairs(vector<int>& cost) {
f[0] = f[1] = 0;
int n = cost.size();
for(int i=2;i<=n;i++)
{
f[i] = min(cost[i-1]+f[i-1],cost[i-2]+f[i-2]); //也是递归思想,存储了之前的方案
}
return f[n];
}
};
198. Robbery
class Solution {
//注意当n=1时直接返回dp[0]即可,但是需进行一个dp[1]最大的判断(确定边界),然后找出状态转移方程
#define maxn 110
int dp[maxn];
public:
int rob(vector<int>& nums) {
dp[0] = nums[0];
int n = nums.size();
for(int i=1;i<n;i++)
{
if(i==1)
dp[1] = max(nums[0],nums[1]);
else {
dp[i] = max(dp[i-1],dp[i-2] + nums[i]);//这会进行一次判断,当i-2时加上本身和i-1时判断(判断触发是否少拿一个临近的大,还是多拿一个大)
}
}
return dp[n-1];
}
};
213. Robbery II
class Solution {
#define maxn 110 //这题的边界为第一个选还是不选
int dp[maxn][2]; //dp[i][0]表示在到第i个元素为止,第一个元素不选,dp[i][1]表示到第i-1个元素为止,第一个元素选取
public:
int rob(vector<int>& nums) {
//因为首尾相连,讨论选0还是选1这个问题
int n = nums.size();
if(n==1)
return nums[0];
else if(n==2)
return max(nums[0],nums[1]);//判断临界条件n=0|1时
dp[0][1] = nums[0];
dp[0][0] = 0;
for(int i=0;i<n;i++)
{
for(int j=0;j<2;j++)
{
if(i==1){
if(j==0)
{
dp[i][j] = nums[1];
}
else dp[i][j] = nums[0];
}
else if(i==n-1&&j==1)
{
dp[i][j] = dp[i-1][j];
}
else {
dp[i][j] = max(dp[i-1][j],dp[i-2][j]+nums[i]);
}
}
}
return max(dp[n-1][0],dp[n-1][1]);
}
};//这题一直过不了编译,不理解,但是算法是对的
91. Decoding method
class Solution {
#define maxn 115
int dp[maxn];
public:
int numDecodings(string s) {
int len=s.size();
int n=len;
for(int i=0;i<len;i++)
{
dp[i] = 0;
if(i==0){
dp[i] = (s[i]=='0')?0:1;
}
else {
if(s[i]!='0')
{
dp[i] += dp[i-1];
}
if(i>=1&&(s[i-1]=='1'||s[i-1]=='2'))//i==1这个临界注意写上
{
int val =(s[i-1]-'0')*10 + s[i]-'0';
if(val<=26){
if(i==1){
dp[i]++;
}
else {
dp[i] += dp[i-2];//这一步加dp[i-2]相当于把i-1和第i位合并成一个数字映射,而前面的加上dp[i-1]是相当于把它看成数字单独映射(这一步是把两种情况进行了合并,关键一步,比较难懂)
}
}
}
}
}
return dp[n-1];
}
};
1646. Get the maximum value in the generated array
class Solution {
#define maxn 110
int nums[maxn];
public:
int getMaximumGenerated(int n) {
nums[0] = 0;
nums[1] = 1;
for(int i=0;i<n;i++)
{
if(2<=2*i && 2*i<=n)
{
nums[2*i] = nums[i];
}
if(2<=2*i+1 && 2*i+1<=n)
{
nums[2*i+1] = nums[i] +nums[i+1];
}
}
int v = nums[0];
for(int i=1;i<=n;i++)
{
v = max(v ,nums[i]);
}
return v;
}
};//这题直接告诉了状态转移方程,我们求最大值
1043. Split an array to get maximum sum
class Solution {
//这个没看懂
#define maxn 1010
int dp[maxn];
public:
int maxSumAfterPartitioning(vector<int>& arr, int k) {
int maxv,cnt;
int n = arr.size();
for(int i=0;i<n;i++)
{
maxv = 0;
cnt = 0;
dp[i] = 0;
for(int j=i;j>=0;j--)
{
if(arr[j]>maxv)
maxv = arr[j]; //找到最大值
cnt++;
if(cnt>k) break;
if(j){
dp[i] = max(dp[i],dp[j-1] + maxv * cnt);//
}
else {
dp[i] = max(dp[i],cnt*maxv);//判断小于0的情况
}
}
}
return dp[n-1];
}
};
139. Word splitting
This question uses suffix testing and dynamic programming ideas
where dp[i] is the state. If we can splice the first i strings through wordDict, then dp[i] is 0, otherwise 0
Problem-solving ideas
This problem uses suffix test and dynamic programming ideas
where dp[i] is the state. If we can splice the first i strings through wordDict, then dp[i] is 0, otherwise it is 0
Then we need to traverse the enumeration dp[i] to sum each String to perform suffix matching
The dictionary is too long to skip matching. The first i-1 strings cannot be matched and skip matching. If no suitable suffix is found for matching, the loop will be jumped out
class Solution {
//其中第二个if里面的判断一点要注意是判断i-l即为上一个后缀匹配
#define maxn 510
int dp[maxn];
public://按位匹配
bool wordBreak(string s, vector<string>& wordDict) {
//字典太长跳过匹配,前i-1字符串个为不能匹配跳过匹配,找不到合适的后缀进行匹配则跳出循环
int n = s.size();
int i,j,l,k;
memset(dp,0,sizeof(dp));
for(i = 0;i<n;++i)
{
for(j=0;j<wordDict.size();++j)
{
l = wordDict[j].size();
if(i-l+1<0)//长度是否匹配
{
continue;
}
if(i-l!=-1&&!dp[i-l])//!dp[i-l]是为了验证上一个后缀是否匹配,如果不匹配,则直接跳过,i-l!=-1是为了看是否为第一个匹配如果为第一个匹配则不需要判断后缀匹配
{
continue;
}
for(k=0;k<l;k++)
{
if(s[i-l+1+k]!=wordDict[j][k])
break;
}
if(k==l)
{
dp[i]=1;
break;
}
}
}
return dp[n-1];
}
};
1869. Which consecutive substring is longer?
class Solution {
#define maxn 110
int dp[2][maxn];//dp[0][i]表示以第i个数结尾且连续'0'的个数,dp[1][i]表示以第i个数结尾连续'1'的数
int maxv[2];
public:
bool checkZeroOnes(string s) {
int n = s.size();
memset(dp,0,sizeof(dp));
maxv[0] = maxv[1] =0;
dp[s[0]-'0'][0] = 1;
maxv[s[0]-'0'] = 1;
for(int i=1;i<n;++i)
{
if(s[i]==s[i-1])
{
dp[s[i]-'0'][i] = dp[s[i]-'0'][i-1] + 1;
} else {
dp[s[i]-'0'][i] = 1;
}
maxv[0] = max(maxv[0],dp[0][i]);
maxv[1] = max(maxv[1],dp[1][i]);
}
return (maxv[1] > maxv[0]);
}
};
724. Find the center index of an array
class Solution {
#define maxn 10100
int sum[maxn];
public:
int pivotIndex(vector<int>& nums) {
//状态转换方程 感觉这题的转换方程并不是分麻烦,前缀和比较多
int n = nums.size();
memset(sum,0,n);
sum[0] = nums[0];
for(int i=1;i<n;i++)
{
sum[i] = sum[i-1] + nums[i];
}
if(sum[n-1] == sum[0])
return 0;
for(int i=1;i<n;i++)
{
if(sum[i-1] == sum[n-1] - sum[i])
return i;
}
return -1;
}
};
1277. Square submatrix whose statistics are all ones
class Solution {
#define maxn 310
bool mat[maxn][maxn][maxn];//开三维是为了
public:
int countSquares(vector<vector<int>>& matrix) {
int l,j,i;
int n = matrix.size();
int m = matrix[0].size();
int len = min(m,n);
int ans = 0;
for(l=1;l <=len;l++)//l是控制搜索的宽度
{
for(i=0;i+l<=n;i++)
{
for(j=0;j+l<=m;j++)
{
if(l==1)
mat[l][i][j] = matrix[i][j];
else
mat[l][i][j] = matrix[i][j]&&mat[l-1][i+1][j]&&mat[l-1][i][j+1]&&mat[l-1][i+1][j+1];
ans +=mat[l][i][j];
}
}
}
return ans;
}
};