题目1(最长回文子串)
示例 1
输入:
“ababc”
复制
返回值:
3
复制
说明:
最长的回文子串为"aba"与"bab",长度都为3
示例 2
输入:
“abbba”
复制
返回值:
5
复制
示例 3
输入:
“b”
复制
返回值:
1
复制
收获
1:这道题是自己在尝试那么多的动态回归自己独立写出来的,还是有丢丢成就感滴~
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
bool isHuiWen(int start,int end,string A){
int i=start;
stack<int >st;
while(i<=end){
st.push(A[i]);
i++;
}
i=start;
while(i<=end){
char temp=st.top();
st.pop();
if(A[i]!=temp)
return false;
i++;
}
return true;
}
int getLongestPalindrome(string A) {
// write code here
vector<int >dp(A.size(),1);
int maxN=1;
for(int i=1;i<A.size();i++)
for(int j=0;j<i;j++){
if(isHuiWen(j,i,A)&&dp[i]<dp[j]+1){
dp[i]=i-j+1;
maxN=max(dp[i],maxN);
}
}
return maxN;
}
};
题目2(打家劫舍一)
收获
1:这题是可以对每一家进行判断,选择劫舍或不,dp[i]表示至第i家为止能够截取的最大金额
代码
**class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型
*/
int rob(vector<int>& nums) {
// write code here
vector<int>dp(nums.size()+1,0);
dp[1]=nums[0];
for(int i=2;i<=nums.size();i++){
dp[i]=max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[nums.size()];
}
};**
题目3(大家劫舍二)
示例 1
输入:
[1,2,3,4]
复制
返回值:
6
复制
说明:
最优方案是偷第 2 4 个房间
示例 2
输入:
[1,3,6]
复制
返回值:
6
复制
说明:
由于 1 和 3 是相邻的,因此最优方案是偷第 3 个房间
收获
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型
*/
int rob(vector<int>& nums) {
// write code here
vector<int>dp(nums.size()+1,0);
//选择偷第一家
dp[1]=nums[0];
for(int i=2;i<nums.size();i++){
//对于每家可以选择偷和不偷
dp[i]=max(dp[i-1],dp[i-2]+nums[i-1]);
}
int res=dp[nums.size()-1];
dp.clear();
//选择不偷第一家
dp[1]=0;
for(int i=2;i<=nums.size();i++){
//对于每家可以选择偷和不偷
dp[i]=max(dp[i-1],dp[i-2]+nums[i-1]);
}
return max(res,dp[nums.size()]);
}
};
题目4(编辑距离一)
示例 1
输入:
“nowcoder”,“new”
复制
返回值:
6
复制
说明:
“nowcoder”=>“newcoder”(将’o’替换为’e’),修改操作1次
“nowcoder”=>“new”(删除"coder"),删除操作5次
示例 2
输入:
“intention”,“execution”
复制
返回值:
5
复制
说明:
一种方案为:
因为2个长度都是9,后面的4个后缀的长度都为"tion",于是从"inten"到"execu"逐个修改即可
示例 3
输入:
“now”,“nowcoder”
复制
返回值:
5
复制
收获
1:dp[i][j]表示到str1[i],str2[j]为止的子串需要的编辑距离
经典的动态规划解法,记 dp[i][j] 表示将 str10~i 编辑成 str20~j 的代价,如果 str1i=str2j,那么 dp[i][j] 就可以直接从 dp[i-1][j-1] 转移过来,否则就比较插入、删除和替换三种操作哪种的代价小:
如果 str10~i-1 已经编辑成了 str20~j-1,只需要将 str1i 替换为 str2j 可以完成转换,代价为 dp[i-1][j-1]+rc
如果 str10~i-1 已经被编辑为 str20~j,只需要将 str10~i 删除一个 str1i 就可以完成转换,代价为 dp[i-1][j]+dc
如果 str10~i 已经被编辑为 str2 0~j-1,只需要插入一个 str2j 就可以完成转换,代价为 dp[i][j-1]+ic
本题中 3 种编辑代价不做区分,都看做一种操作,因此代价相同。
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str1 string字符串
* @param str2 string字符串
* @return int整型
*/
int editDistance(string str1, string str2) {
// write code here
int n1=str1.length();
int n2=str2.length();
vector<vector<int > >dp(n1+1,vector<int >(n2+1,0));
for(int i=1;i<=n1;i++)
dp[i][0]=dp[i-1][0]+1;
for(int i=1;i<=n2;i++)
dp[0][i]=dp[0][i-1]+1;
for(int i=1;i<=n1;i++)
for(int j=1;j<=n2;j++){
if(str1[i-1]==str2[j-1])
dp[i][j]=dp[i-1][j-1];
else{
dp[i][j]=min(dp[i-1][j-1]+1,min(dp[i-1][j],dp[i][j-1])+1);
}
}
return dp[n1][n2];
}
};
题目5(买卖股票的最好时机一)
示例 1
输入:
[8,9,2,5,4,7,1]
复制
返回值:
5
复制
说明:
在第3天(股票价格 = 2)的时候买入,在第6天(股票价格 = 7)的时候卖出,最大利润 = 7-2 = 5 ,不能选择在第2天买入,第3天卖出,这样就亏损7了;同时,你也不能在买入前卖出股票。
示例 2
输入:
[2,4,1]
复制
返回值:
2
复制
示例 3
输入:
[3,2,1]
复制
返回值:
0
复制
收获
1:学会了这种定义大小为2的情况,虽然自己还没有具体的细致理解,但是大概懂了思想
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param prices int整型vector
* @return int整型
*/
int maxProfit(vector<int>& prices) {
// write code here
int n=prices.size();
//dp[i][1]表示某天持股,到该天为止的收益,dp[i][0]表示某天不持股,到该天的最大距离
vector<vector<int >>dp(n,vector<int >(2,0));
dp[0][0]=0;
dp[0][1]=-prices[0];
for(int i=1;i<n;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);
dp[i][1]=max(dp[i-1][1],-prices[i]);
}
return dp[n-1][0];
}
};
题目6(买卖股票的最好时机二)
示例 1
输入:
[8,9,2,5,4,7,1]
复制
返回值:
7
复制
说明:
在第1天(股票价格=8)买入,第2天(股票价格=9)卖出,获利9-8=1
在第3天(股票价格=2)买入,第4天(股票价格=5)卖出,获利5-2=3
在第5天(股票价格=4)买入,第6天(股票价格=7)卖出,获利7-4=3
总获利1+3+3=7,返回7
示例 2
输入:
[5,4,3,2,1]
复制
返回值:
0
复制
说明:
由于每天股票都在跌,因此不进行任何交易最优。最大收益为0。
示例 3
输入:
[1,2,3,4,5]
复制
返回值:
4
复制
说明:
第一天买进,最后一天卖出最优。中间的当天买进当天卖出不影响最终结果。最大收益为4。
备注:
总天数不大于200000。保证股票每一天的价格在[1,100]范围内。
收获
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算最大收益
* @param prices int整型vector 股票每一天的价格
* @return int整型
*/
int maxProfit(vector<int>& prices) {
// write code here
int n=prices.size();
//dp[i][1]表示某天持股,到该天为止的收益,dp[i][0]表示某天不持股,到该天的最大距离
vector<vector<int >>dp(n,vector<int >(2,0));
dp[0][0]=0;
dp[0][1]=-prices[0];
for(int i=1;i<n;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
}
return dp[n-1][0];
}
};
题目7(买卖股票的最好时机三)
示例 1
输入:
[8,9,3,5,1,3]
复制
返回值:
4
复制
说明:
第三天(股票价格=3)买进,第四天(股票价格=5)卖出,收益为2
第五天(股票价格=1)买进,第六天(股票价格=3)卖出,收益为2
总收益为4。
示例 2
输入:
[9,8,4,1]
复制
返回值:
0
复制
示例 3
输入:
[1,2,8,3,8]
复制
返回值:
12
复制
说明:
第一笔股票交易在第一天买进,第三天卖出;第二笔股票交易在第四天买进,第五天卖出;总收益为12。
因最多只可以同时持有一只股票,所以不能在第一天进行第一笔股票交易的买进操作,又在第二天进行第二笔股票交易的买进操作(此时第一笔股票交易还没卖出),最后两笔股票交易同时在第三天卖出,也即以上操作不满足题目要求。
备注:
总天数不大于200000。保证股票每一天的价格在[1,100]范围内。
收获
1:定义数组大小为5,并用循环来表示每次处理的值
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 两次交易所能获得的最大收益
* @param prices int整型vector 股票每一天的价格
* @return int整型
*/
int maxProfit(vector<int>& prices) {
// write code here
int n=prices.size();
vector<vector<int >>dp(n,vector<int >(5,-10000));
dp[0][0]=0;
dp[0][1]=-prices[0];
for(int i=1;i<n;i++){
dp[i][0]=dp[i-1][0];
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i]);
dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i]);
dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i]);
}
return max(dp[n-1][2],dp[n-1][4]);
}
};
题目8(最长的括号子串)
示例 1
输入:
“(()”
复制
返回值:
2
复制
示例 2
输入:
“(())”
复制
返回值:
4
复制
收获
1:采用压栈的方式,左括号入栈,右括号则对当前栈内进行判断,为空怎么样,不为空怎么样,最后使用res进行记录,记得不要忘记设置start为-1即遍历的前一个,同时入栈的是序号而不是左右括号
代码
class Solution {
public:
/**
*
* @param s string字符串
* @return int整型
*/
int longestValidParentheses(string s) {
// write code here
int start=-1;
int res=0;
stack<int >st;
for(int i=0;i<s.size();i++){
if(s[i]=='(')
st.push(i);
else{
if(st.empty())
start=i;
else{
st.pop();
if(!st.empty()){
res=max(res,i-st.top());
}else{
res=max(res,i-start);
}
}
}
}
return res;
}
};
题目9(正则表达式匹配)
示例 1
输入:
“aaa”,“aa"
复制
返回值:
true
复制
说明:
中间的可以出现任意次的a,所以可以出现1次a,能匹配上
示例 2
输入:
“aad”,“cad”
复制
返回值:
true
复制
说明:
因为这里 c 为 0 个,a被重复一次, * 表示零个或多个a。因此可以匹配字符串 “aad”。
示例 3
输入:
“a”,”."
复制
返回值:
true
复制
说明:
"." 表示可匹配零个或多个('‘)任意字符(’.')
示例 4
输入:
“aaab”,"aaac"
复制
返回值:
false
复制
收获
1:觉得对正则表达式的理解更多了点,不再像以前那么害怕了
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @param pattern string字符串
* @return bool布尔型
*/
bool match(string str, string pattern) {
// write code here
int n1=str.length();
int n2=pattern.length();
vector<vector<bool >>dp(n1+1,vector<bool >(n2+1,false));
dp[0][0]=true;
//待匹配的字符串为空时的初始化
for(int i=2;i<=n2;i++){
if(pattern[i-1]=='*')
dp[0][i]=dp[0][i-2];
}
for(int i=1;i<=n1;i++)
for(int j=1;j<=n2;j++){
//当前是.或者相等时
if(pattern[j-1]!='*'&&(pattern[j-1]=='.'||pattern[j-1]==str[i-1])){
dp[i][j]=dp[i-1][j-1];
}
//当前是*时
else if(j>=2&&pattern[j-1]=='*'){
//如果前一个是.或者前一个和当前的匹配的话,则*起作用,
//当前的也和当前的匹配,所以dp[i][j]取绝于模板的前2个
//和字符串的前1个
if(pattern[j-2]=='.'||pattern[j-2]==str[i-1])
dp[i][j]=dp[i-1][j]||dp[i][j-2];
else
dp[i][j]=dp[i][j-2];
}
}
return dp[n1][n2];
}
};
题目10(数字字符转换成ip地址)
示例 1
输入:
“25525522135”
复制
返回值:
[“255.255.22.135”,“255.255.221.35”]
复制
示例 2
输入:
“1111”
复制
返回值:
[“1.1.1.1”]
复制
示例 3
输入:
“000256”
复制
返回值:
“[]”
复制
收获
1:这道题最开始怎么看也看不懂,看了参考代码不明白,step的意思后来才理解原来是对应的当前处理到第几个数了,因为ip地址最大只能包含4个数字,同时每个字符串内需要处理的最大是3,所以学到了唔~
2:看网上一些说的好像是可以理解为分治的思想,把大问题变成处理这样的小问题,对每一个里面的数字进行判断,再处理一些边界条件,相比较就会容易了一些~
代码
class Solution {
public:
/**
*
* @param s string字符串
* @return string字符串vector
*/
vector<string >res;
string nums;
void dfs(int step,int index,string s){
string cur="";
if(step==4){
if(index!=s.length())
return;
res.push_back(nums);
}else{
for(int i=index;i<index+3&&i<s.length();i++){
cur+=s[i];
int num=stoi(cur);
string temp=nums;
if(num<=255&&(cur.length()==1||cur[0]!='0')){
if(step-3!=0)
nums+=cur+'.';
else
nums+=cur;
dfs(step+1,i+1,s);
nums=temp;
}
}
}
}
vector<string> restoreIpAddresses(string s) {
// write code here
dfs(0,0,s);
return res;
}
};