leetcode-寻找最长回文字符串(第五题)
@: 2018-10-28
题目描述如下:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example 2:
Input: “cbbd”
Output: “bb”
思路:
假设参数为str, 遍历str, 一边遍历一遍存储各个字符出现的位置, 我们用一个数组来标记各个字符出现的次数, 用一个二维数组来标记字符在str中出现的位置.用max保存回文字串的长度.
比如: times[256]标记次数,那么position[str[i]][times[str[i]]] = i就可以保存字符str[i]在position中第几次出现以及出现在str中的哪里.
在遍历时, 如果str[i]出现的次数大于1(说明出现了两次以上), 那么我们就从str[i]第一次出现的位置到str[i]此次出现的位置(此次为当前的最后一次)之间进行遍历, 先判断两者之间的长度是否大于长度max, 如果不大于max则break, 没有必要进行判断是否回文了, 因为就算是回文子串, 已经有比它更长的回文子串了; 如果大于max, 则判断两者之间的字符串是否是回文字符串.
判断回文字符串的方法:
因为回文字符串是中间对称的, 所以我们只需要判断这个字符串是否是对称的就行, 此处不再赘述.
总之, 假如我们以"ababab"为例子:
-
循环变量 i 遍历字符串
-
i == 2时, 'a’出现了两次, position[‘a’][1] = i;
-
从’a’出现的第一次的位置开始(即第一次为str[0]), 先判断两者之间的距离是否大于当前最长回文字符串的长度max, 如果不是则继续遍历字符串. 如果是则进行下一步.
-
判断两者之间的子字符串是否是回文字符串, 如果是则改变max的值, 并且记录此最长字符串的开始和结束的位置(因为返回值是string类型的), 继续遍历字符串, 如果不是则进行下一步.
-
继续判断’a’第二次出现的位置(一直到当前位置 -1)到当前位置两者之间的字符串是否是子字符串(当然, 先判断长度), 因为此时i == 2, 'a’只出现了两次, 所以此时不会进行这一步.(假设i==3的话, 'a’出现了三次, 也就是说先判断’a’第一次出现到第三次出现之间是否是回文字符串, 如果是则跳出, 继续遍历字符串, 如果不是则判断’a’第二次出现到第三次出现之间是否是回文字符串)
程序结束.
代码如下, 时间复杂度为O(n ^ 3)
string longestPalindrome(string str)
{
int position[256][1000] = { 0 };
int times[256] = { 0 };
int length = str.length();
int i;
int temp;
int max = 0;
int max_left = 0, max_right = 0;
int left, right;
/**
* @遍历字符串
*/
for (i = 0; i < length; i++)
{
/**
* @记录各个字符的位置与次数
*/
times[str[i]]++;
temp = times[str[i]] - 1;
position[str[i]][temp] = i + 1;
/**
* @从第一出现开始, 判断是否是回文字符串, position[str[i]][0]是第一次出现的位置, position[str[i]][temp]是最后一次出现的位置, temp为出现次数 - 1.
*/
for (int j = 0; j < temp; j++)
{
left = position[str[i]][j], right = position[str[i]][temp];
/**
* @长度判断
*/
if (right - left + 1 <= max)
break;
bool substr = true;
for (int k = left; k < (right + left) / 2; k++)
{
if (str[k] != str[right - k + left - 2])
{
substr = false;
break;
}
}
if (substr)
{
max_left = left - 1;
max_right = right - 1;
max = max_right - max_left + 1;
break;
}
}
}
string max_str = "";
for (i = max_left; i <= max_right; i++)
max_str += str[i];
return max_str;
}
在网上看到有大神说有个马拉车算法是专门解决回文字符串的问题的, 时间复杂度为O(n), 日后再补充.