• 最长回文子串--动态规划


    给定一个字符串s,找到s中最长的回文子串. 你可以假设 s 的最大长度为1000.

    示例1

    输入: "babad"
    输出: "bab"
    注意: "aba" 也是一个有效答案。

    示例2

    输入: "cbbd"
    输出: "bb"

    解法一: 暴力解法

    根据回文子串的定义,枚举所有长度大于等于2的子串,以此判断它们是否是回文.在具体实现中,可以只针对大于“当前得到的最长回文子串长度”的子串进行回文子串.下面我们用暴力解法,列举出所有的,但是时间超出了限制,但是还是将这种方式贴出来

    import Foundation //想要导入,否则string无subString方法
    func longestPalindrome(_ s: String) -> String {
        guard s.count > 0 else {return ""}
        if s.count == 1 {return s}
        var maxLen: Int = 1
        
        let range = NSRange(location: 0, length: 1)
        let result = (s as NSString).substring(with: range)
        var resultStr = result as String
        
        for i in 0..<s.count - 1 {
            for j in i + 1..<s.count {
                if j - i + 1 > maxLen && valid(s, left1: i, right1: j) {
                    maxLen = j - i + 1
                    let range = NSRange(location: i, length: maxLen)
                    let result = (s as NSString).substring(with: range)
                    resultStr = result
                }
            }
        }
        return resultStr
    }
    //判断回文
    func valid(_ s: String, left1: Int, right1: Int) -> Bool {
        let strArr = Array(s)
        var left: Int = left1
        var right: Int = right1
        while left < right {
            if strArr[left] != strArr[right]  {
                return false
            }
            left = left + 1
            right -= 1
        }
        return true
    }

    然后在leetCode上提交,但是时间超过了限制,给出的结果如下:

     

    解法二: 动态规划

    解法一的时间复杂度过高,在leetCode上并不能AC.下面有改进方法

    首先我们定义P(i,j) 如下 

    接下来

    P( i , j ) = (P( i + 1,  j - 1 )&& S[ i ] == S[ j ])

    所以如果我们知道了P( i, j )的情况,不需要调用判断回文串的函数了,只需要知道P( i + 1,  j - 1 )的情况就可以了,这样时间复杂度就会减少了O(n), 因此我们采取动态规划的方案,用空间换取时间,把已经求出来的P(i, j)存储起来.

    如果S[i + 1, j -1]是回文串, 那么只要S[i] == S[j] 就可以确定S[i, j]是回文串.

    求长度为1和长度为2的P(i,j)时不能用上边的公式,因为带上去,发现越界,所以要分两种情况考虑.

    所以我们先初始化长度为1的回文串的P(i,j),利用上面的提出的公式,然后两边向外各扩充一个字符,长度为3, 5的,所有的长度就求出来了.

    同理, 初始化长度为2的回文串,利用公式,得到了长度为4, 6的所有偶数长度就都求出来了.

    代码如下:

    class Solution {
        public String longestPalindrome(String s) {
        int length = s.length();
        if (length == 1){return s;}
        boolean[][] P = new boolean[length][length];
        int maxLen = 0;
        String maxPal = "";
        for (int i = 1; i <= length; i++) //遍历所有的长度
        for (int j = 0; j < length; j++) {
            int k = i + j - 1;
            if (k >= length) //下标已经越界,结束本次循环
            break;
            P[j][k] = (i == 1 || i == 2 || P[j + 1][k - 1]) && s.charAt(j) == s.charAt(k); //长度为 1 和 2 的单独判断下
            if (P[j][k] && k > maxLen) {
                maxPal = s.substring(j, k + 1);
            }
        }
        return maxPal;
    }
    }

    上面就是动态规划方法,还会持续更新,希望大家关注!!!

  • 相关阅读:
    面试题
    关于TDD的想法
    GAMS 基础语法
    不要迷信数据
    在Microsoft AJAX Library下JavaScript的面向对象开发
    应用OOP的设计过程演化(一)
    应用OOP的设计过程演化(二)
    探索AJAX中的消息传输模式(一)
    应用OOP的设计过程演化(三)
    SecureCRT 6.0.2和SecureFX 6.0.2 软件 及 注册机
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/11800983.html
Copyright © 2020-2023  润新知