算法-回文问题

1.回文串

(1)让字符串成为回文串的最小插入次数–动归

在这里插入图片描述

class Solution {
    public int minInsertions(String s) {
        int n=s.length();
        int[][] dp=new int[n][n];
        dp[0][0]=0;
        for(int i=n-2;i>=0;i--){
            for(int j=i+1;j<n;j++){
                if(s.charAt(i)==s.charAt(j)){
                    dp[i][j]=dp[i+1][j-1];
                }else{
                    //选择向字符串左边或者右边添加一个字符使之成为回文子串
                    dp[i][j]=Math.min(dp[i+1][j],dp[i][j-1])+1;
                }
            }
        }
        return dp[0][n-1];
    }
}

(2)求回文子串个数–动归

在这里插入图片描述

class Solution {
    public int countSubstrings(String s) {
        int n=s.length();
        boolean[][] dp=new boolean[n][n];
        int ans=0;
        for(int j=0;j<n;j++){
            for(int i=0;i<=j;i++){
                //(1)一个字符(如'a'),肯定是回文串 j-i==0
                //(2)两个相等字符(如"aa")j-i==1
                //(3)当前位置i和j对应的字符相等,则需判断dp[i+1][j-1]
                if(s.charAt(i)==s.charAt(j) && ((j-i<2) || dp[i+1][j-1])){
                    dp[i][j]=true;
                    ans++;
                }
            }
        }
        return ans;
    }
}

(3)最长回文子串–双指针

在这里插入图片描述

class Solution {
    public String longestPalindrome(String s) {
        int n=s.length();
        if(n<2) return s;
        int begin=0;//最长回文子串起始位置
        int maxLen=1;//最长回文子串最大长度
        char[] c=s.toCharArray();
        for(int j=0;j<n;j++){
            for(int i=0;i<=j;i++){
                if(j-i+1>maxLen && isPalindrome(c,i,j)){
                    begin=i;
                    maxLen=j-i+1;
                }
            }
        }
        return s.substring(begin,begin+maxLen);
    }
    // public boolean isPalindrome(String s,int left,int right){
    //     while(left<right){
    //         if(s.charAt(left)!=s.charAt(right)){
    //             return false;
    //         }
    //         left++;
    //         right--;
    //     }
    //     return true;
    // }
    public boolean isPalindrome(char[] c,int left,int right){
        while(left<right){
            if(c[left]!=c[right]){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

}

转化成字符数组进行回文子串的判断比直接使用字符串进行单个字符的对比进行判断要快很多。

(4)最长回文串

在这里插入图片描述

class Solution {
    public int longestPalindrome(String s) {
        //统计每个字符个数,ASCII共有128个字符
        int[] count=new int[128];
        int n=s.length();
        char[] c=s.toCharArray();
        for(char ch:c){
            count[ch]++;
        }
        //计算最长回文串长度
        int res=0;
        for(int v:count){
            res+=v/2*2;
            if(v%2==1 && res%2==0){
                res++;
            }
        }
        return res;

    }

}

官方题解:

可以将每个字符使用偶数次,使得它们根据回文中心对称。
在这之后,如果有剩余的字符,可以再取出一个,作为回文中心。

对于每个字符 ch,假设它出现了 v 次,我们可以使用该字符 v / 2 * 2 次,在回文串的左侧和右侧分别放置 v / 2 个字符 ch,其中 / 为整数除法。
例如若 “a” 出现了 5 次,那么我们可以使用 “a” 的次数为 4,回文串的左右两侧分别放置 2 个 “a”。

如果有任何一个字符 ch 的出现次数 v 为奇数(即 v % 2 == 1),那么可以将这个字符作为回文中心,注意只能最多有一个字符作为回文中心。
在代码中,我们用 ans 存储回文串的长度,由于在遍历字符时,ans 每次会增加 v / 2 * 2,因此 ans 一直为偶数。但在发现了第一个出现次数为奇数的字符后,我们将 ans 增加 1,这样 ans 变为奇数,在后面发现其它出现奇数次的字符时,我们就不改变 ans 的值了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值