leetcode Ch2-Dynamic Programming II
方法一、一维DP
class Solution
{
public:
int longestValidParentheses(string s)
{
vector<int> dp(s.size(),);
int res=;
for(int i=s.size()-;i>=;i--)
{
if(s[i]==')')
dp[i]=;
else
{
int j=i+dp[i+]+;
if(j<s.size()&&s[j]==')')
{
dp[i]+=dp[i+]+;
if(j+<s.size())
dp[i]+=dp[j+];
}
}
res=max(res,dp[i]);
}
return res;
}
};
像这种连续的子串,类似于最大连续子串和,在dp时往往是以某位置为结尾/起点。
dp[i]表示以s[i]为起点的最长连续括号数。下标j表示跨越了以s[i+1]为起点的一连串括号后到达的位置。如果该位置s[j]为'(' ,那说明以该'('为起点的有效括号数必然是0(否则就应该被包含进以s[i+1]为起点的有效括号串里了);而如果该位置s[j]为')',那正好和s[i]的'('匹配起来,因此s[i]可基于s[i+1]的基础上再加2,而且,除此之外还要再加上s[j+1] 。
ref1: Lexi's
#2: 忘的太快。很多细节: 判断 j < n 和 j + 1 < n。
方法二、栈
二、 Regular Expression Matching
DP解法:
class Solution
{
public:
bool isInterleave(string s1,string s2,string s3)
{
int m=s1.size(),n=s2.size();
if(m+n!=s3.size()) return false;
vector<vector<int>> f(m+,vector<int>(n+,));
f[][]=true;
for(int i=;i<=m;i++)
f[i][]=f[i-][]&&(s1[i-]==s3[i-]);
for(int i=;i<=n;i++)
f[][i]=f[][i-]&&(s2[i-]==s3[i-]);
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
f[i][j]=(s1[i-]==s3[i+j-] && f[i-][j])||(s2[j-]==s3[i+j-] && f[i][j-]);
return f[m][n];
}
};
f[i][j]表示s1从下标0开始长度为i的子串,与s2从下标0开始长度为j的子串,它们与s3从0开始长度为i+j的子串是否是interleave string。
注意这里的i,j都是长度。所以转换为下标时别忘了减1.
另外,在line8初始化时如果是以0为初始值,那就别忘了专门把f[0][0]赋值为1。
细节很多,易出错。
#2: good.
class Solution
{
public:
int maximalSquare(vector<vector<char>> &matrix)
{
if(matrix.empty()) return ;
int m=matrix.size(),n=matrix[].size();
vector<vector<int>> f(m,vector<int>(n,));
int res=;
for(int i=;i<m;i++)
{
f[i][]=matrix[i][]-'';
res=max(res,f[i][]);
}
for(int i=;i<n;i++)
{
f[][i]=matrix[][i]-'';
res=max(res,f[][i]);
}
for(int i=;i<m;i++)
{
for(int j=;j<n;j++)
{
if(matrix[i][j]=='')
{
f[i][j]=min(min(f[i-][j],f[i][j-]),f[i-][j-])+;
res=max(res,f[i][j]);
}
else f[i][j]=;
}
}
return res*res;
}
};
dp[i][j]表示以(i,j)为右下角的最大正方形的边长。那么,可得递推公式:dp[i][j]= min( dp[i-1][j] , dp[i][j-1] , dp[i-1][j-1] ) + 1;
该递推式可以先直观感受一下:
若该点周围3个点最小的dp值为0(即至少有一个点是‘0’),那最大正方形边长必然是1(即该点本身);
若该点周围3个点最小的dp值为1,那么至少这3个点都是‘1’,所以已经可以构成一个边长为2的正方形;
...
#2: 一堆细节易出错。题目要求的是面积,不是边长,所以最后返回的是res * res; 第一行和第一列要特殊处理,同时把它们的值都要跟res比一下并更新res。
class Solution
{
public:
int minCut(string s)
{
int n=s.size();
vector<int> f(n+,);
vector<vector<int>> p(n,vector<int>(n,));
for(int i=;i<=n;i++)
f[i]=n--i;
for(int i=n-;i>=;i--)
{
for(int j=i;j<n;j++)
{
if(s[i]==s[j]&&(j-i<||p[i+][j-]))
{
p[i][j]=;
f[i]=min(f[i],f[j+]+);
}
}
}
return f[];
}
};
设len=s.size(), f[i]表示从s[i]开始一直到s[len-1]这段子串的minCut数(显然,最大值即为这段子串包含的字符数减1)。
这里之所以有除了f[0]~f[len-1]之外还有个f[len]= -1,是因为后面会用到。
p[i][j]表示s[i...j]这段子串是否是回文串。判断依据就是 if ( s[i]==s[j] && (j-i<2 || p[i+1][j-1]) ) ,这个如果成立则说明s[i...j]是个回文串,那么就可以尝试更新一下 f[i]=min(f[i] , f[j+1]+1) ,即如果在j和j+1之间cut一下,那么s[i...len-1]即分成了s[i...j]和s[j+1...len-1],此时的cut数等于f[j+1]+1.
ref: soul, spring
#2: 太容易忘。
O(n) space: 【非最优】
class Solution
{
public:
int maxProduct(vector<int> &nums)
{
int n=nums.size();
vector<int> dp_max(n,);
vector<int> dp_min(n,);
int res=dp_max[]=dp_min[]=nums[];
for(int i=;i<n;i++)
{
dp_max[i]=max(nums[i],max(dp_max[i-]*nums[i],dp_min[i-]*nums[i]));
dp_min[i]=min(nums[i],min(dp_max[i-]*nums[i],dp_min[i-]*nums[i]));
res=max(res,dp_max[i]);
}
return res;
}
};
O(1) space 【最优】
class Solution
{
public:
int maxProduct(vector<int> &nums)
{
int n=nums.size();
int maxsofar,minsofar,maxpre,minpre;
int res=maxsofar=minsofar=maxpre=minpre=nums[];
for(int i=;i<n;i++)
{
maxsofar=max(nums[i],max(maxpre*nums[i],minpre*nums[i]));
minsofar=min(nums[i],min(maxpre*nums[i],minpre*nums[i]));
res=max(res,maxsofar);
maxpre=maxsofar;
minpre=minsofar;
}
return res;
}
};
#2: 细节容易出错。
七、 Decode Ways
class Solution
{
public:
int numDecodings(string s)
{
int n=s.size();
if(n==) return ;
vector<int> dp(n+,);
dp[]=;
if(s[]!='') dp[]=;
for(int i=;i<=n;i++)
{
if(s[i-]!='')
dp[i]+=dp[i-];
if(s[i-]==''||(s[i-]=='' && s[i-]<=''))
dp[i]+=dp[i-];
}
return dp[n];
}
};
dp[i]里的i表示长度,即从下标0开始的长度为i的子串的decode ways数。
要特别注意,dp[0]值为1。这是为了递推后面的值的需要。
与climb stairs是类似的。 可以用滚动数组优化空间复杂度。
Backpack
Backpack II
k Sum
k Sum II
Minimum Adjustment Cost
leetcode Ch2-Dynamic Programming II的更多相关文章
- [LeetCode] 139. Word Break_ Medium tag: Dynamic Programming
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...
- [LeetCode] 45. Jump Game II_ Hard tag: Dynamic Programming
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- [LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- [LeetCode] 63. Unique Paths II_ Medium tag: Dynamic Programming
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...
- [LeetCode] 121. Best Time to Buy and Sell Stock_Easy tag: Dynamic Programming
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...
- [LeetCode] 53. Maximum Subarray_Easy tag: Dynamic Programming
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- [LeetCode] 312. Burst Balloons_hard tag: 区间Dynamic Programming
Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...
- [LeetCode] 64. Minimum Path Sum_Medium tag: Dynamic Programming
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...
- [LeetCode] 72. Edit Distance_hard tag: Dynamic Programming
Given two words word1 and word2, find the minimum number of operations required to convert word1to w ...
- [LeetCode] 152. Maximum Product Subarray_Medium tag: Dynamic Programming
Given an integer array nums, find the contiguous subarray within an array (containing at least one n ...
随机推荐
- 【Kafka】Kafka集群搭建
一.准备工作 服务器:最好是多台,大于等于2 已经搭建好的zookeeper集群 下载软件kafka_2.11-0.10.0.1.tgz 二.创建目录 #创建目录 cd /opt/ mkdir kaf ...
- struts2上传单个文件
项目目录: struts.xml配置: <constant name="struts.enable.DynamicMethodInvocation" value=" ...
- 虚拟机实现finally语句块
1.ret.jsr.jsr_w与returnAddress指令实现finally语句块 当class文件的版本号等于或高于51.0,jsr和jsr_w这两个操作码也不能出现在code数组中. 所有re ...
- np.random.random()函数 参数用法以及numpy.random系列函数大全
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9751471.html 1.np.random.random()函数参数 np.random.r ...
- [中英对照]vmlinuz Definition | vmlinuz的定义
vmlinuz Definition | vmlinuz的定义 vmlinuz is the name of the Linux kernel executable.vmlinuz是Linux内核可执 ...
- STL 排序(转载)
这篇文章关于STL中的排序写的虽不深入,但是还是挺好的. 1.sort sort有两种形式,第一种形式有两个迭代器参数,构成一个前开后闭的区间,按照元素的 less 关系排序:第二种形式多加一个指定排 ...
- Kernel的IIC驱动分析
涉及到的文件: drivers/i2c/i2c-core.c drivers/i2c/i2c-dev.c drivers/i2c/busses/i2c-imx.c 等等 在下面分析的代码中,不想关或者 ...
- 使用 pjax 实现无刷新切换页面
一.目的 1.当打开链接的时候,页面是淡入显示,并且页面顶部会显示加载进度条,页面显示完成时,进度条加载满并且消失. 2.点击页面上的 a 标签时,显示加载进度条,并且当前页面淡出消失,当前页面淡出消 ...
- .net core mvc 类库读取配置文件
appsettings.json,给类库项目引入 Microsoft.Extensions.Configuration 和 Microsoft.Extensions.Configuration.J ...
- Linux下一个最简单的不依赖第三库的的C程序(1)
如下代码是一段汇编代码,虽然标题中使用了C语言这个词语,但下面确实是一段汇编代码,弄清楚了这个代码,后续的知识点才会展开. simple_asm.s: #PURPOSE: Simple program ...