LeetCode 题解(67): Longest Palindromic Substring

题目:

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length ofS is 1000, and there exists one unique longest palindromic substring.

题解:

首先学习了一下LeetCode讨论区里的DP解法,空间复杂度O(n^2),Memory Limit Exceeded无法通过:

class Solution {
public:
    string longestPalindrome(string s) {
        if(!s.length())
            return NULL;
        
        int** score = new int*[s.length()];
        for(int i = 0; i < s.length(); i++)
            score[i] = new int[s.length()];
        
        int max = 1, start = 0, end = 0;
        
        for(int row = 0; row < s.length(); row++)
            for(int col = 0; col < s.length(); col++) {
                if(row == col)
                    score[row][col] = 1;
                else if(row == col - 1 && s[row] == s[col]) {
                    score[row][col] = 2;
                    max = 2;
                    start = row;
                    end = col;
                }
                else
                    score[row][col] = 0;
            }
                
        for(int outer = s.length() - 2; outer > 0; outer--)
            for(int inner = 0; inner < outer; inner++) {
                int endIndex = inner+s.length()-outer;
                if(s[inner] == s[endIndex] && score[inner+1][endIndex-1] > 0) {
                    score[inner][endIndex] = score[inner+1][endIndex-1] + 1;
                    if(score[inner][endIndex] > max) {
                        max = score[inner][endIndex];
                        start = inner;
                        end = endIndex;
                    }
                }
            }
            
        return s.substr(start, end - start + 1);
    }
};

只好继续寻求减少空间的方法,继续学习 LeetCode讨论区的解法:

A simpler approach, O(N2) time and O(1) space:
In fact, we could solve it in O(N2) time without any extra space.

We observe that a palindrome mirrors around its center. Therefore, a palindrome can be expanded from its center, and there are only 2N-1 such centers.

2N-1个中心是怎么得来的?N个字符,每个可以作为一个中心进行扩展,同时,N-1个字符之间的缝隙也可以作为中心扩展(如"abba",ab和ba中的缝隙向两边扩展得到abba),所以总共有N+N-1=2N-1个中心。

这种向两边expand的方法比较直观,代码也好写,于是得到此150ms解法:

class Solution {
public:
    string longestPalindrome(string s) {
        if(!s.length())
            return NULL;
        
        int max = 1, start = 0, end = 0;
        
        for(int i = 1; i <= s.length(); i++) {
            int localMax = 1, localStart = i-1, localEnd = i-1;
            for(int j = 0; j < min(i-1, static_cast<int>(s.length()-i)); j++) {
                if(s[i-j-2] == s[i+j]) {
                    localMax += 2;
                    localStart = i-j-2;
                    localEnd = i + j;
                }
                else
                    break;
            }
            if(localMax > max) {
                max = localMax;
                start = localStart;
                end = localEnd;
            }
        }
        
        for(int m = 0; m < s.length()-1; m++) {
            if(s[m] == s[m+1]) {
                int localMax = 2, localStart = m, localEnd = m + 1;
                for(int n = 0; n < min(m, static_cast<int>(s.length()-m-2)); n++) {
                    if(s[m-n-1] == s[m+n+2]) {
                        localMax += 2;
                        localStart = m - n - 1;
                        localEnd = m + n + 2;
                    }
                    else
                        break;
                }
                if(localMax > max) {
                    max = localMax;
                    start = localStart;
                    end = localEnd;
                }
            }
        }
        
        return s.substr(start, end-start+1);
    }
};

Java版:

尝试把字符和缝隙两种情况写在一起了,逻辑上有点混乱,最后把自己绕迷糊了:

public class Solution {
    public String longestPalindrome(String s) {
        int max = 1, start = 0, end = 0;
        for(int i = 0; i < s.length() * 2 - 1; i++) {
            int localMax = 0, localStart = 0, localEnd = 0;
            if(i % 2 == 0) {
                localMax = 1;
                for(int j = 0; j < Math.min(i / 2, s.length() - i / 2 - 1); j++) {
                    if(s.charAt(i / 2 - j - 1) == s.charAt(i / 2 + j + 1)) {
                        localMax += 2;
                        localStart = i / 2 - j - 1;
                        localEnd = i / 2 + j + 1;
                    }
                    else 
                        break;
                }
            } else {
                for(int j = 0; j <= Math.min(i / 2, s.length() - i / 2 - 2); j++) {
                    if(s.charAt(i / 2 - j) == s.charAt(i / 2 + j + 1)) {
                        localMax += 2;
                        localStart = i / 2 - j;
                        localEnd = i / 2 + j + 1;
                    }
                    else
                        break;
                }
            }
            if(localMax > max) {
                max = localMax;
                start = localStart;
                end = localEnd;
            }
        }
        return s.substring(start, end+1);
    }
}

Python版:

class Solution:
    # @return a string
    def longestPalindrome(self, s):
        longest = 1
        begin = 0
        end = 0
        for i in range(0, len(s)):
            localLongest = 1
            localBegin = 0
            localEnd = 0
            for j in range(0, min(i, len(s)-i-1)):
                if s[i-j-1] == s[i+j+1]:
                    localLongest += 2
                    localBegin = i - j - 1
                    localEnd = i + j + 1
                else:
                    break
            if localLongest > longest:
                longest = localLongest
                begin = localBegin
                end = localEnd
                
        for m in range(0, len(s)-1):
            if s[m] == s[m+1]:
                localLongest = 2
                localBegin = m
                localEnd = m + 1
                for n in range(0, min(m, len(s)-m-2)):
                    if s[m-n-1] == s[m+n+2]:
                        localLongest += 2
                        localBegin = m - n - 1
                        localEnd = m + n + 2
                    else:
                        break
                if localLongest > longest:
                    longest = localLongest
                    begin = localBegin
                    end = localEnd
        return s[begin:end+1]




你可能感兴趣的:(Algorithm,LeetCode,面试题)