Leetcode#5. Longest Palindromic Substring(最長迴文子串:二種解法)
阿新 • • 發佈:2019-01-06
宣告:題目解法使用c++和Python兩種,重點側重在於解題思路和如何將c++程式碼轉換為python程式碼。
本題c++採用兩種方法解答,python用到了閉包的知識。
題目
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.
Example:
Input: “cbbd”
Output: “bb”
題意
給你一個字串s,求出s中的最長迴文子串輸出。
首先你要知道什麼是迴文?
一個字串從左向右讀和從右向左讀一樣。
例如aba。
思路一:列舉
直接列舉所有的子串,判斷是否迴文。
- 時間複雜度為:O(n^3)
QAQ果斷超時。
class Solution {
public:
int Palindrome(string s)
{
for(int i=0; i<s.size(); i++)
if(s[i] != s[s.size()-1-i])
return 0;
return 1;
}
string longestPalindrome(string s)
{
string temp = "",res;
int i,j,k,ms = 0;
for(i=0; i<s.size(); i++)
{ temp = "";
for(j=i; j<s.size(); j++)
{
temp += s[j];
if(Palindrome(temp)==1 )
{
if(ms<temp.size())
{
ms = temp.size();
res = temp;
}
}
}
}
return res;
}
};
思路二:對稱列舉
從字串的某一位置,作為對稱中心位置,向兩側掃描檢測最長迴文長度 。
- 時間複雜為0(n*n)
class Solution {
public:
string ss;
int dfs(int left, int right)
{
if(left<0 || right >=ss.size() ||ss[left] !=ss[right])
return left+1;
else
//一定要有返回的出口,前方高能,卡了我一下午
return dfs(left-1,right+1);
}
string longestPalindrome(string s)
{
ss = s;
string res="";
int i,ms = 0,now_left,len,sx=0;
for(i = 0; i + 1 <s.size(); i ++ )
{
if(s[i]==s[i+1]) //偶數
{
now_left = dfs(i,i+1);
len = (i-now_left+1)*2;
if(ms<len)
{
ms = len;
sx = now_left;
}
}
if(i-1>=0&&s[i-1]==s[i+1])//奇數
{
now_left = dfs(i-1,i+1);
len = (i-now_left)*2+1;
if(ms<len)
{
ms = len;
sx = now_left;
}
}
}
//找不到迴文字串,返回第一個數
if(ms==0)
res+=s[0];
for(i=sx; i<sx+ms;i++)
res+=s[i];
return res;
}
};
Python程式碼
這裡用到了python高階函式中的閉包:
內層定義一個判斷迴文的函式呼叫外層還是中的s變數,稱之為閉包。內層函式無法被外部訪問。
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#使用外部函式的區域性引數
def dfs(left, right):
if left < 0 or right >= len(s) or s[left] != s[right]:
return (left + 1)
else:
return dfs(left-1, right+1)
ms = 0
now_left = 0
sx = 0
for i in range(0,len(s)-1):
if s[i] == s[i+1]:
now_left = dfs(i, i+1)
now_len = (i-now_left+1)*2
if ms<now_len:
ms = now_len
sx = now_left
if i-1>=0 and s[i-1] == s[i+1]:
now_left = dfs(i-1, i+1)
now_len = (i-now_left)*2+1
if ms<now_len:
ms = now_len
sx = now_left
res = ""
if ms == 0:
res+=s[0]
for i in range(sx,sx+ms):
res+=s[i]
return res
前方高能
在寫程式的時候犯了一個低階的錯誤:
是這樣的
int dfs(int left, int right)
{
if(left<0 || right >=ss.size() ||ss[left] !=ss[right])
return left+1;
else
//錯誤點
dfs(left-1,right+1);
}
沒有返回,這樣導致的錯誤是在多次呼叫dfs導致函式沒有返回值或者直接得到一個系統隨意分配的值。
最後貼一個九章算術裡面的思路相同的一個寫法,用#填充字串,不用考慮奇偶性。
class Solution {
public:
string longestPalindrome(string s) {
string str = "", ans = "";
int len = s.length();
int maxl = -1, cnt;
for (int i = 0; i < len; i++) {
str += '#';
str += s[i];
}
str += '#';
// 將原字串擴充套件成#a#b#的形式可以直接列舉長度,不用考慮迴文串長度的奇偶性
for (int i = 1; i < 2 * len; i++) {
cnt = 0;
while ((i - cnt >= 0) && (i + cnt <= 2 * len) && (str[i - cnt] == str[i + cnt]))
cnt++;
cnt--;
if (cnt > maxl) {
maxl = cnt;
ans = s.substr((i - cnt) / 2, (i + cnt) / 2 - (i - cnt) / 2);
}
}
return ans;
}
};