回文子串汇总

647. 回文子串

一、中心扩展法1:


        1. 以k为中心:  left=k-1, right=k+1   (回文串长度 > 1 且 为奇数时)
        2. 以k右边的空白位置为中心: left=k, right = k+1   (回文串长度 > 1 且 为偶数时)

class Solution {
    public int countSubstrings(String s) {
        int n = s.length();
        char[] letters = s.toCharArray();
        int ans = n;
        for (int k = 0; k < n; k++) {
            // 以letters[k]为中心向两边扩(回文串长度为奇数)
            int i = k - 1, j = k + 1;
            while (i >= 0 && j < n && letters[i] == letters[j]) {
                i--;
                j++;
                ans++;
            }
            // 以letters[k]右侧的空白位置为中心向两边扩(回文串长度为偶数)
            i = k;
            j = k + 1;
            while (i >= 0 && j < n && letters[i] == letters[j]) {
                i--;
                j++;
                ans++;
            }
        }
        return ans;
    }
}

复杂度:

时间:O(n^2)

空间:O(1)

一、中心扩展法2:

1. 扩展中心点是 left 和 right 的起始点,如果以一个字符为中心点进行扩展,abab这个序列永远搜搜不出来,所以扩展的中心点分为 1个(n种可能) 和 2个(n-1中可能),一共2n-1个

2. center为中心点,算出left、right与center之间的关系:
            int left = center / 2;
            int right = left + center % 2;

3. 外层for循环遍历中心点,内层while() 进行向外扩展并判断

class Solution {
    public int countSubstrings(String s) {
        // 中心扩展法,
        int ans = 0;
        for (int center = 0; center < 2 * s.length() - 1; center++) {
            // left和right指针和中心点的关系是
            int left = center / 2;
            int right = left + center % 2;

            while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
                ans++;
                left--;
                right++;
            }
        }
        return ans;
    }
}

复杂度:

时间:O(n^2)

空间:O(1)

二、动态规划法:

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 < s.length(); j++) {
            for (int i = 0; i <= j; i++) {
                if (s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1])) {
                    dp[i][j] = true;
                    ans++;
                }
            }
        }

        return ans;
    }
}

复杂度:

时间:O(n^2)

空间:O(n^2)


5. 最长回文子串

 一、中心拓展法(遍历n次):

因为ans初值为n,进入while循环的都是回文串长度 > 1的情况,所以这里设置index标记回文串长度是超过1

class Solution {
    public String longestPalindrome(String s) {
        boolean index = false;
        int n = s.length();
        char[] letters = s.toCharArray();
        int ans = n;
        String res = "";
        String tmp = "";
        for (int k = 0; k < n; k++) {
            // 以letters[k]为中心向两边扩
            int i = k - 1, j = k + 1;
            while (i >= 0 && j < n && letters[i] == letters[j]) {
                index = true;
                tmp = s.substring(i, j + 1);
                if (tmp.length() > res.length()) {
                    res = tmp;
                }
                i--;
                j++;
                ans++;

            }
            // 以letters[k]右侧的空白位置为中心向两边扩
            i = k;
            j = k + 1;
            while (i >= 0 && j < n && letters[i] == letters[j]) {
                index = true;
                tmp = s.substring(i, j + 1);
                if (tmp.length() > res.length()) {
                    res = tmp;
                }
                i--;
                j++;
                ans++;
            }
        }

        return index == true? res: s.substring(0,1);
    }
}

复杂度:

时间:O(n^2)

空间:O(1)

 二、中心拓展法(遍历2n-1次):

class Solution {
    public String longestPalindrome(String s) {
        //中心拓展法,遍历2n-1次
        int n = s.length();
        String tmp = "";
        for(int k = 0; k < 2*n-1; k++){
            int left = k / 2;
            int right = left + k % 2;
            while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)){
                tmp = tmp.length() < s.substring(left, right+1).length() ? s.substring(left, right+1) : tmp;
                left--;
                right++;
            }
        }
        return tmp;
    }
}

复杂度:

时间:O(n^2)

空间:O(1)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值