String (Palindrome) - LeetCode

119 阅读1分钟

Q5 Longest Palindromic Substring

Given a string s, return the longest palindromic substring in s.

Example 1:

Input: s = "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: s = "cbbd"
Output: "bb"

Example 3:

Input: s = "a"
Output: "a"

Example 4:

Input: s = "ac"
Output: "a"

Constraints:

  • 1 <= s.length <= 1000
  • s consist of only digits and English letters (lower-case and/or upper-case),

解法及注释

class Solution {
    public String longestPalindrome(String s) {
        //pre-check
        if(s == null || s.length() == 0)
            return "";
        
        int start = 0, end = 0;
        for(int i = 0; i < s.length(); i++) {
            int oddLen = getRes(s, i, i);
            int evenLen = getRes(s, i, i + 1);
            int len = Math.max(oddLen, evenLen);
            if(len > end - start) {
                start = i - (len - 1) / 2;
                end = i + len / 2;
            }
        }
        return s.substring(start, end + 1);
        
    }
    
    private int getRes(String str, int left, int right) {
        int l = left, r = right;
        while(l >= 0 && r < str.length() && str.charAt(l) == str.charAt(r)) {
            l--;
            r++;
        }
        return r - l - 1;
    }
}

Q516 Longest Palindromic Subsequence

Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000.

Example 1:
Input:

"bbbab"

Output:

4

One possible longest palindromic subsequence is "bbbb".

Example 2:
Input:

"cbbd"

Output:

2

One possible longest palindromic subsequence is "bb".

Constraints:

  • 1 <= s.length <= 1000
  • s consists only of lowercase English letters.

解法及注释

class Solution {
    public int longestPalindromeSubseq(String s) {
        //pre-check
        if(s == null || s.length() == 0)
            return 0;
        
        //DP solution
        int n = s.length();
        //states
        int[][] f = new int[n][n];
        for(int len = 1; len <= n; len++) {
            for(int i = 0; i + len - 1 < n; i++) {
                int j = i + len - 1;
                if(len == 1)
                    f[i][j] = 1;
                else if(s.charAt(i) == s.charAt(j))
                    f[i][j] = f[i+1][j-1] + 2;
                else 
                    f[i][j] = Math.max(f[i+1][j], f[i][j-1]);
            }
        }
        return f[0][n-1];
    }
}

Q647 Palindromic Substrings

Given a string, your task is to count how many palindromic substrings in this string.

The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.

Example 1:

Input: "abc"
Output: 3
Explanation: Three palindromic strings: "a", "b", "c".

Example 2:

Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

Intuition

Let N be the length of the string. The middle of the palindrome could be in one of 2N - 1 positions: either at letter or between two letters.

For each center, let's count all the palindromes that have this center. Notice that if [a, b] is a palindromic interval (meaning S[a], S[a+1], ..., S[b] is a palindrome), then [a+1, b-1] is one too.

Algorithm

For each possible palindrome center, let's expand our candidate palindrome on the interval [left, right] as long as we can. The condition for expanding is left >= 0 and right < N and S[left] == S[right]. That means we want to count a new palindrome S[left], S[left+1], ..., S[right].

解法及注释

class Solution {
    public int countSubstrings(String s) {
        //pre-check
        if(s == null || s.length() == 0)
            return 0;
        
        //start with center
        int n = s.length(), ans = 0;
        for(int center = 0 ; center <= 2 * n - 1; ++center) {
            int left = center / 2;
            int right = left + center % 2;
            while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)) {
                left--;
                right++;
                ans++;
            }   
        }
        return ans;
    }
}

Q25 Valid Palindrome

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

Note: For the purpose of this problem, we define empty string as valid palindrome.

Example 1:

Input: "A man, a plan, a canal: Panama"
Output: true

Example 2:

Input: "race a car"
Output: false

Constraints:

  • s consists only of printable ASCII characters.

解法及注释

class Solution {
    public boolean isPalindrome(String s) {
        //pre-check
        if(s == null || s.length() == 0)
            return true;
        
        int i = 0, j = s.length() - 1;
        while(i <= j) {
            if(!isAlphanumeric(s.charAt(i)))
                i++;
            else if (!isAlphanumeric(s.charAt(j)))
                j--;
            else {
                if(Character.toUpperCase(s.charAt(i)) == Character.toUpperCase(s.charAt(j))) {
                    i++;
                    j--;
                } else 
                    return false;
            }
        }
        return true; 
    }
    
    private boolean isAlphanumeric(char c) {
        if(c >= 97 && c <= 122)
            return true;
        else if( c >= 65 && c <= 90)
            return true;
        else if(c >= 48 && c <= 57)
            return true;
        return false;
    }
}

Q680 Valid Palindrome II

Given a non-empty string s, you may delete at most one character. Judge whether you can make it a palindrome.

Example 1:

Input: "aba"
Output: True

Example 2:

Input: "abca"
Output: True
Explanation: You could delete the character 'c'.

Note:

  1. The string will only contain lowercase characters a-z. The maximum length of the string is 50000.

解法及注释

class Solution {    public boolean validPalindrome(String s) {        //pre-check        if(s == null || s.length() == 0 || s.length() > 10e5) {            return false;        }        int left = 0, right = s.length() - 1;        while(left < right) {            if(s.charAt(left) != s.charAt(right)) {                return validRestString(s, left + 1, right) || validRestString(s, left, right - 1);            }            left++;            right--;        }        return true;    }    private boolean validRestString(String s, int left, int right) {        String str = s.substring(left, right + 1);        String reverse = new StringBuilder(str).reverse().toString();        return str.equals(reverse);    }}

you may also use two pointers as below 

class Solution {    public boolean validPalindrome(String s) {        //pre-check        if(s == null || s.length() == 0 || s.length() > 10e5) {            return false;        }        int left = 0, right = s.length() - 1;        while(left <= right) {            if(s.charAt(left) == s.charAt(right)) {                left++;                right--;            } else {                return isPalindrome(s, left + 1, right) || isPalindrome(s, left, right - 1);            }        }        return true;    }    private boolean isPalindrome(String str, int left, int right) {        while(left <= right) {            if(str.charAt(left) != str.charAt(right)) {                return false;            }            left++;            right--;        }        return true;    }}