Palindrome 问题

Longest Palindromic Substring

middle-out 由每个字符作为起点,往两边扫。

Palindrome 长度可能是奇数,也可能是偶数。所以指定 seed 往两边扩展的时候要注意先把 start / end 指针推到“不是 seed” 的位置上。

public class Solution {
    public String longestPalindrome(String s) {
        if(s == null || s.length() <= 1) return s;
        if(s.length() == 2) {
            if(s.charAt(0) == s.charAt(1)) return s;
            else return s.substring(1);
        }

        int maxLen = 1;
        int maxStart = 0, maxEnd = 0;

        for(int i = 0; i < s.length(); i++) {
            // the palindrome length could be even or odd, so we need put the pointer on postion which is not seed
            int left = i - 1;
            while(left >= 0 && s.charAt(left) == s.charAt(i)) left--;

            int right = i + 1;
            while(right < s.length() && s.charAt(right) == s.charAt(i)) right++;

            while(left >= 0 && right < s.length()) {
                if(s.charAt(left) == s.charAt(right)) {
                    left--;
                    right++;
                } else {
                    break;
                }
            }
            // update the longest 
            if(right - end - 1 > maxLen) {
                maxLen = right - end - 1;
                maxStart = left + 1;
                maxEnd = right - 1;
            }
        }

        return s.substring(maxStart, maxEnd + 1);
    }
}

方法二:思路基本一样,就是写法上有一点不同 基本思路是对于每个子串的中心(可以是一个字符,或者是两个字符的间隙,比如串abc,中心可以是a,b,c,或者是ab的间隙,bc的间隙)往两边同时进行扫描,直到不是回文串为止。

public class Solution {
    public String longestPalindrome(String s) {
        if(s == null || s.length() == 0) return s;

        String result = "";
        int max = 1;

        // we go over the center point of each substring, it could be a char 
        // or a gap bewtween two char
        for(int i = 0; i < 2 * s.length() - 1; i++) {
            // middle out
            int left = i / 2;
            int right = i / 2;
            // in the gap
            if(i % 2 == 1) {
                right++;
            }

            String str = getPalindrome(s, left, right);

            if(str.length() > max) {
                result = str;
                max = str.length();
            }
        }

        return result;
    }

    public String getPalindrome(String s, int i, int j) {
        while(i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)) {
            i--;
            j++;
        }
        return s.substring(i + 1, j);
    }
}

时间复杂度:O(n^2)

Valid Palindrome

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

把s都变成小写,跳过非alphanumeric 的字符

public class Solution {
    public boolean isPalindrome(String s) {
        if(s == null || s.length() < 2) return true;
        s = s.toLowerCase();

        int start = 0;
        int end = s.length() - 1;

        while (start < end) {
            while(start < end && !Character.isLetterOrDigit(s.charAt(start))) {
                start++;
            }
            while(start < end && !Character.isLetterOrDigit(s.charAt(end))) {
                end--;
            }

            if(s.charAt(start) != s.charAt(end)) return false;

            start++;
            end--;
        }
        return true;
    }
}

(Snapchat) Make Palindrome

给一个string,算出把他变成palindrome的最少操作数。操作包括,增加,删减以及修改。

思路: 既然是找最小操作数,那么肯定是用动归的方法。 因为是palindrome,我们可以考虑用区间型动归。

dp[i][j] 表示从i到j的substring变成palindrome 需要的最小操作数

初始化对角线

转移方程: dp[i][j] = if (s[i] == [j]) dp[i+1][j - 1], else Math.min(dp[i][j-1], dp[i + 1][j]) + 1

问题:修改,增加和删除有什么不同?

results matching ""

    No results matching ""