没弄过ACM的人表示刷leetcode还是有压力的!!!!看着别人的神思路,和对题目的分析还有入手点,让我真后悔大一没去搞搞ACM锻炼锻炼思维啊= = 目前比较遗憾的两件事就是大一没参加到学生会,和没有刷ACM题。
就好比这题,求最长回文子串 Given a string S, find the longest palindromic substring in S。 判断回文这个简单,但是在一个字符串找子串而且找是回文的就稍微复杂了,当然最直接的思路是列出所有子串可能性,并一一判断是否为回文,然而这种算法效率很低,结果超时。
于是上网找了答案,说是一种思路是动态规划。虽然大二期间自己有做过一些ACM题,有涉及动态规划,觉得用到动态规划解决的算法题非常的巧妙,但是死活不知道dp数组应该如何定义,到现在还不太理解动态规划的适用处,希望以后多加练习能有感觉吧。以下是动态规划对题目的一些分析。
1.定义dp数组bool dp[ 1000][1000 ] ;(别问我怎么来的,就是觉得很厉害,我也在慢慢领悟 = = ) dp [ i ] [ j ]记录 字符串s 位置 i 到位置 j是否为回文。
2.位置 i 到 位置 j是回文 前提是 s[ i ] ==s[ j ],然后判断位置 i + 1 到 j - 1是否是回文。
3.若是,则判断当前回文子串是否是最长,如果是,则记录位置,函数末尾返回。否则继续。
以下是代码:
string longestPalindrome(string s){
int length = s.size();
if (length == 0){
return "";
}
if (length == 1){
return s;
}
bool dp[1000][1000];
int max_length = 0;
int result_pos1 = 0;
int result_pos2 = 0;
for (int i = 0; i < length; i++){
for (int j = 0; j < length; j++){
if (i == j ){
dp[i][j] = true;
}
else {
dp[i][j] = false;
}
}
}
for (int i = length - 1; i >= 0; i--){
for (int j = i; j<s.length(); j++){
if (s[i] == s[j] && (i+1>j-1||dp[i+1][j-1])){
dp[i][j] = true;
if (j - i + 1>max_length){
max_length = j - i + 1;
result_pos1 = i;
result_pos2 = j;
}
}
}
}
return s.substr(result_pos1,result_pos2 - result_pos1 +1);
}
需要注意以下这个问题,贴上错误代码,仅修改了赋值dp数组时候的i j起始边界!
/*
错误代码
*/
string longestPalindrome(string s){
cout << s << endl;
int length = s.size();
if (length == 0){
return "";
}
if (length == 1){
return s;
}
bool dp[1000][1000];
int max_length = 0;
int result_pos1 = 0;
int result_pos2 = 0;
for (int i = 0; i < length; i++){
for (int j = 0; j < length; j++){
if (i == j ){
dp[i][j] = true;
}
else {
dp[i][j] = false;
}
}
}
/*
这样设置边界错误!导致在判断dp[i][j]的时候,由于先判断较长的子串i到j是否为回文时,依照的是判断i+1到j-1是否为回文
但由于更小的范围dp[i+1][j-1]还处于初始化默认的状态,而未被计算后重新赋值,所以遍历时应该从最小子串开始遍历!!
*/
for (int i = 0; i<length;i++){
for (int j = i; j<s.length(); j++){
if (s[i] == s[j] && (i+1>j-1||dp[i+1][j-1])){
cout << "Match when i is " << i << " j is " << j << " length is " << j - i + 1 << " max_length is " << max_length << endl;
dp[i][j] = true;
if (j - i + 1>max_length){
max_length = j - i + 1;
result_pos1 = i;
result_pos2 = j;
}
}
}
}
cout << "result .... pos1 is " << result_pos1 << " pos2 is " << result_pos2 << endl;
return s.substr(result_pos1,result_pos2 - result_pos1 +1);
}