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 ...
随机推荐
- JavaScript数据结构-15.二叉树
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- latex排版(CTeX winEdit输出“系统找不到指定的文件”的终极解决办法)
WinEdit的菜单栏中:Options->Execution Modes 弹出的界面见下面的图: 看上图中“1”所示位置,后面3项出现了“?”号(出现“系统找不到指定的文件”的错误时,所有项后 ...
- To B服务想做移动化?腾讯云案例了解一下
本文由 腾讯云助手团队 发布于 腾讯云云+社区 | 导语:腾讯云那么多资源和服务,就不能手机管理吗? 能. 当用户在使用To B服务时,往往会遇到各种各样的限制: 1.操作难度:涉及各种权限.多重验证 ...
- NetXray
NetXRay是由Cinco Networks公司开发的一个用于高级分组检错的软件,功能很强大.IP地址查询工具. 硬件要求 对硬件要求低,可运行常用的windows平台. 主要功能 1.监视网络状态 ...
- Lineare Algebra
Grundlegendes Wort: 矩阵列:Das Spalte von der Matrix 行列式:Die Determinante 对角矩阵:Die diagonal Matrix 逆矩阵: ...
- MySQL---1、介绍
一.MySQL简介 1.MySQL简介 MySQL是一个轻量级关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司.目前MySQL被广泛地应用在Internet上的中小型网站 ...
- photoshop cc 2014 下载安装及汉化资源及切图简要使用教程
这是百度经验上一个pscc 2014 版本的下载安装汉化教程,亲测有效: http://jingyan.baidu.com/article/647f0115bce3847f2148a80c.html ...
- C# DateTime类型和sqlserver DateTime精度不同
在最近的项目中, 有个关于时间的功能.一个请假的时间.前端选择的时候只有日期.所以比如请一天假就是选2017-8-15和2017-8-15,这样算请这一天的假.但是后台存入数据库时我不能就存2017- ...
- 使用auth_request模块实现nginx端鉴权控制
使用auth_request模块实现nginx端鉴权控制 nginx-auth-request-module 该模块是nginx一个安装模块,使用配置都比较简单,只要作用是实现权限控制拦截作用.默认高 ...
- protobuf简单测试应用
protobuf是google推出的一种数据交换协议,比较适合应用于底层服务交互,nodejs提供protobufjs包的实现,下面是一个简单的测试demo: 首先是.proto文件: package ...