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 ...
随机推荐
- 【Ubuntu】命令记录
cp 该命令的功能是将给出的文件或目录拷贝到另一文件或目录中,就如同DOS下的copy命令一样,功能非常强大. 语法: cp [选项] 源文件或目录 目标文件或目录 说明:该命令把指定的源文件复制到目 ...
- windows 3389 远程
3389常用命令: 1.查询终端端口 REG query HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server\WinSt ...
- PHP在 win7 64位 旗舰版 报错 Call to undefined function curl_init()
代码在ubuntu下无缝运行OK 转到我的win7 64位 期间 学习机上 报错: Call to undefined function curl_init() 因为用到curl 远程抓取数据. 所以 ...
- [问题解决]Fresco设置圆角效果不生效问题探究
[问题解决]Fresco设置圆角效果不生效问题探究 /** * Created by diql on 2017/2/21 11:07:04. */ 问题 在View中设置: fresco:rounde ...
- 解决Ubuntu 18.04中文输入法的问题
https://ywnz.com/linuxjc/1637.html
- json test
public static void main(String[] args) { class B { String name; public String getName() { return nam ...
- IE的if条件判断
我们经常需要编写兼容代码,特别是万恶的IE. 特此记录下IE提供的if判断: <!--[if IE 5]> 仅IE5.0与IE5.5可以识别 <![endif]--> < ...
- jQuery 数据 - jQuery.data() 方法
打印出 hi
- SSIS教程:创建简单的ETL包 -- 6. 对项目部署模型使用参数(Using Parameters with the Project Deployment Model)
在本课中,将修改在第 5 课: 添加包部署模型的包配置中创建的包,以便使用项目部署模型.您将使用一个参数替换该配置值,以便指定示例数据位置.还可以复制本教程附带的已完成的 Lesson 5 包. 使用 ...
- 关于UI回调Invoker的实现(二)
上篇我说到,光有一个IOperation*的指针,是无法记录这么多事件的.由于无法确定要把回调绑定到哪个事件上,因此,我们需要引入一个中间的传递机制. 没有看到前面的请先查阅上一篇 关于UI回调Inv ...