LeetCode专题
动态规划
32. Longest Valid Parentheses
我们设置
dp[i]为第i位上以")"结尾的最大括号个数,则有三种情况:
- 若结尾为"(",则
dp[i]=0- 若结尾为")",且前一位为"(",则
dp[i]=dp[i-2]+2- 若结尾为")",但前一位也为")",此时我们只需挖空连续的已匹配括号,判断前一位是否为"(",例如
()(())即,此时需要判断s[i-dp[i-1]-1] == '(',若成立则dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2],否则dp[i]=0
class Solution {
public:
int longestValidParentheses(string s) {
// 16.51---16.56
int n=s.size();
// cout<<n<<endl;
if(n==0)
return 0;
int dp[n];
memset(dp,0,sizeof(dp));
if(s[1]==')'&&s[0]=='(')
dp[1]=2;
for(int i=2;i<n;i++){
// cout<<i<<endl;
if(s[i]=='(')
dp[i]=0;
if(s[i]==')'&&s[i-1]=='(')
dp[i]=dp[i-2]+2;
else if(s[i]==')'&&s[i-1]==')'){
if(i-dp[i-1]-1>=0&&s[i-dp[i-1]-1]=='(')
dp[i]=i-dp[i-1]-1-1>=0?dp[i-1]+2+dp[i-dp[i-1]-1-1]:dp[i-1]+2;
else
dp[i]=0;
}
}
//cout<<"hello";
sort(dp,dp+n);
//cout<<dp[n-1];
return dp[n-1];
}
};
213. House Robber II
相对于上一题198. House Robber,此题的改版只是变成了环路的情形,环路只需要考虑
max{偷第1家到第n-1家,偷第二家到第n家}即可.
通用的状态转移公式为:dp[i]=max(dp[i-1],dp[i-2]+nums[i])
class Solution {
public:
int rob(vector<int>& nums) {
int dp[1000];
int dp2[1000];
if(nums.size()==0)
return 0;
if(nums.size()==1)
return nums[0];
if(nums.size()==2)
return max(nums[0],nums[1]);
dp[0]=nums[0];
dp[1]=max(nums[0],nums[1]);
//环路,即为第1家和最后一家只能偷一个
// 从第1家偷到第n-1家
for(int i=2;i<nums.size()-1;i++){
dp[i]=max(dp[i-1],dp[i-2]+nums[i]);
}
// 从第2家偷到第n家
dp2[0]=nums[1];
dp2[1]=max(nums[2],nums[1]);
for(int i=2;i<nums.size()-1;i++){
dp2[i]=max(dp2[i-1],dp2[i-2]+nums[i+1]);
}
return max(dp[nums.size()-2],dp2[nums.size()-2]);
}
};
718. Maximum Length of Repeated Subarray
首先得区分最长公共子序列LCS和最长公共子串,通常,substr都指的是连续的字符串,而公共子序列则可以不用连续。
因而对这两种题型解法不同:
子序列
/* dp状态转移方程:
* dp[i][j]表示str1长度为i,str2长度为j时的最长公共子序列的值
* str1[i]=str2[j],dp[i][j] = dp[i-1][i-1] + 1
* str1[i]!=str2[j], dp[i][j] = max{dp[i-1][j],dp[i][j-1]}
* 初始化二维dp数组均为0
* /
子串
/ dp状态转移方程:
* dp[i][j]表示str1长度为i,str2长度为j时的最长公共子串的值
* str1[i]=str2[j],dp[i][j] = dp[i-1][i-1] + 1
* 只有连续等于才行,初始化均为0
* */
最长公共子序列
class Solution {
public:
int findLength(vector<int>& A, vector<int>& B) {
int len1=A.size();
int len2=B.size();
int dp[len1+1][len2+1];
memset(dp,0,sizeof(dp));
for(int i=0;i<=len1;i++){
for(int j=0;j<=len2;j++){
if(i==0||j==0)
dp[i][j]=0;
else if(A[i-1]==B[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[len1][len2];
}
};
最长公共子串
class Solution {
public:
int findLength(vector<int>& A, vector<int>& B) {
int len1=A.size();
int len2=B.size();
int dp[len1+1][len2+1];
memset(dp,0,sizeof(dp));
int max=-1;
for(int i=0;i<len2;i++)
if(A[0]==B[i])
dp[0][i]=1;
for(int i=0;i<len1;i++)
if(A[i]==B[0])
dp[i][0]=1;
for(int i=1;i<len1;i++){
for(int j=1;j<len2;j++){
if(A[i]==B[j])
dp[i][j]=dp[i-1][j-1]+1;
max=max>dp[i][j]?max:dp[i][j];
}
}
return max;
}
};