1. 程式人生 > >Leetcode#5. Longest Palindromic Substring(最長迴文子串:二種解法)

Leetcode#5. Longest Palindromic Substring(最長迴文子串:二種解法)

宣告:題目解法使用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;

    }

};