明天就要上课了,再过几天又要见班主任汇报项目进程了,什么都没做的我竟然有一种迷之淡定,大概是想体验一波熬夜修仙的快乐了。不管怎么说,每天还是要水一篇博文,写一个LeetCode的题才圆满。
题目:Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example: Input: "babad" ; Output: "bab"; Note: "aba" is also a valid answer.
第一想法是遍历的过程用堆栈做,想了半天觉得脑子一片空白,放弃,之后看了solution,提到了动态规划,有了想法。太久没刷题了。。。
class Solution { public: string longestPalindrome(string s) { bool flags[s.size()][s.size()]; //flags[i][j]为true,表示s[i]到s[j]位回文子串 for(int i =0;i<s.size();i++){ for(int j = 0; j< s.size();j++){ flags[i][j] = (i==j )? true:( j == i+1? (s[i]==s[j]):false); } } int longest = 1; //标记最长回文子串的长度 int start = 0; //标记最长回文子串的起始位置 for(int i = 0; i<s.size()-1;i++){ //寻找有没有bb这样的回文串,然后更新longest和start if (flags[i][i+1] == true){ longest = 2; start = i; break; } } for(int i = s.size()-3; i>=0;i--){ for (int j = i+2; j < s.size(); j++){ if(s[i]==s[j]&&flags[i+1][j-1]==true){ flags[i][j] = true; longest = longest>(j-i+1)?longest:(j-i+1); start = longest>(j-i+1)?start:i; } } } return s.substr(start,longest); } };
提交之后96ms,击败20%。这么慢,我要哭了。O(n2)的时间复杂度和空间复杂度。继续看solution。。。
从中心扩充:这个解法时间复杂度为O(n2),但是空间复杂度为O(1)
每一个回文子串都含有一个中心,因此一个长度为n的字符串,含有2n-1个回文子串的中心,因为回文子串的中心可以是字母,可以是空白,比如aba、aa。
出去浪了一把,代码没写完,明天补上~不能保卫祖国,就好好学习报效祖国吧。
好了,今天来补代码吧。23ms,击败了42%。写代码的时候干了一件傻事,每次找到回文子串要更新三个参数,因为三个参数不是一开始就设置好的,最后加了一个参数flag,想都没想直接在longest之后添加了flag的更新,导致flag不正确,结果错误。这个逻辑错误也是我经常犯的,今后一定要注意参数的更新顺序是否正确。
class Solution { public: string longestPalindrome(string s) { int longest = 0; //回文中心到边缘的长度 int center = 0; int i = 1; bool flag = true; //标记回文子串的中心是字母还是空,true为字母 while(i<=s.size()-1){ int j = 1,now = 0; while(i-j>=0 && s[i+j] == s[i-j] && i+j <s.size()){ //寻找类似于ABA的回文子串 now++; j++; } center = now>=longest?i:center; flag = now>=longest?true:flag; longest = now>=longest?now:longest; //now == longest的时候也要更新子串,因为aba和aa的longest都为1,但是aba比aa长 j = 1; now = 0; while(s[i-j]==s[i+j-1] && i-j>=0 && i+j-1<s.size()){ //寻找类似于AA这样的回文子串 now++; j++; } center = now>longest?i:center; flag = now>longest?false:flag; longest = now>longest?now:longest; i++; } return flag?s.substr(center-longest,2*longest+1):s.substr(center-longest,2*longest); } };
看了3ms的答案,发现了一个小trick,就是i的更新不用每次都+1,可以直接把i,也就是回文子串的中心更新成回文子串的最右边,因为不存在以原回文子串的中心到右边的任一位置为中心的回文子串长度长与原子串。还有可以用start和len来代替center、longest、flag三个参数,start表示回文开始,len代表回文长度。