LeetCode Hot100【5. 最长回文子串】

5. 最长回文子串

自己做

思路1:暴力解,超时

cpp 复制代码
class Solution {
public:
    bool checkPalindrome(const string s) {
        int len = s.size();         //长度 
        int mid = len / 2;          //中轴

        if (len % 2 == 1) {        //子串长为奇数的情况
            for (int i = 0; i <= mid; i++) {
                if (s[mid - i] != s[mid + i])        //发现不对称,即表示这个子串不是回文串
                    return false;
            }
        }
        else {                       //子串长为偶数的情况
            for (int i = 0; i < mid; i++) {
                if (s[i] != s[len - 1 - i])        //发现不对称,即表示这个子串不是回文串
                    return false;
            }
        }

        return true;
    }

    string longestPalindrome(string s) {
        int len = s.size();     //字符串长度
        int max = 1;            //最大长【默认一个字符为回文串】
        string c;               //保存目前子串
        int begin = 0, end = 0; //最长子串的起始和结束位置

        for (int i = 0; i < len; i++) {             //子串起始
            c = s[i];                             //重置子串
            for (int j = i + 1; j < len; j++) {       //子串延伸
                c += s[j];                        //延伸子串
                if (c.size() <= max) {             //必然不可能是最长子串,跳过检测
                }
                else if (checkPalindrome(c) && c.size() > max) {      //更新最长子串【目前的i和j】
                    begin = i;
                    end = j;
                    max = j - i + 1;                    //更新最长长度
                }
            }
        }
        //目前已经找到了最长回文串
        c = "";                 //重置子串
        for (int i = begin; i <= end; i++) {
            c += s[i];
        }
        return c;

    }
};

思路2:

cpp 复制代码
class Solution {
public:
    bool checkPalindrome(const string s,int front,int len) {
        int mid = len / 2;          //中轴

        if (len % 2 == 1) {        //子串长为奇数的情况
            for (int i = 0; i <= mid; i++) {
                if (s[front + mid - i] != s[front + mid + i])        //发现不对称,即表示这个子串不是回文串
                    return false;
            }
        }
        else {                       //子串长为偶数的情况
            for (int i = 0; i < mid; i++) {
                if (s[front + i] != s[front + len - 1 - i])        //发现不对称,即表示这个子串不是回文串
                    return false;
            }
        }

        return true;
    }

    string longestPalindrome(string s) {
        int len = s.size();     //字符串长度
        string c = "";               //保存目前子串

        for (int c_len = len; c_len > 0; c_len--) {       //子串长度从len开始递减
            for (int front = 0; front + c_len <= len; front++) {             //子串
                if (s[front] == s[front + c_len - 1]) {                    //只有当首尾字符一致才检测是否回文串
                    if (checkPalindrome(s,front, c_len)) {        //检测是否回文串
                        //目前已经找到了最长回文串
                        for (int i = front; i <= front + c_len - 1; i++) {
                            c += s[i];
                        }
                        return c;
                    }
            }
        }
        }
       
        //找不到的情况
        c += s[0];
        return c;

    }
};

看题解【想不出最优解】

cpp 复制代码
class Solution {
    public:
        string longestPalindrome(string s) {
            int n = s.size();
            if (n < 2) {            //只有一个字符的边界情况
                return s;
            }

            int max = 1;        //最大回文串长
            int begin = 0;      //最长回文串起始

            vector<vector<bool>> dp(n, vector<bool>(n));      //初始化dp[n][n]标记数组

            for (int i = 0; i < n; i++)
                dp[i][i] = true;                       //所有的单个字符都是回文串

            for (int len = 2; len <= n; len++) {        //子串长度
                for (int i = 0; i < n; i++) {           //子串起始位置
                    int j = i + len - 1;                //子串末尾

                    if (j >= n)                         //超出边界
                        break;

                    if (s[i] != s[j]) {                 //左右两边不相等
                        dp[i][j] = false;               //必然不是回文串
                    }
                    else {                              //左右两边相等
                        if (j - i < 3) {                //偶数或者三个字符的情况
                            dp[i][j] = true;
                        }
                        else {
                            dp[i][j] = dp[i + 1][j - 1];    //本来是回文串现在还是回文串,本来不是回文串就不可能是回文串
                        }
                    }

                    if (dp[i][j] && j - i + 1 > max) {      //如果该段是回文串且长度超过了之前的最大长,更新
                        max = len;
                        begin = i;
                    }

                }
                
            }
            
            //此时得到了最大回文串的长度和起始位置
            return s.substr(begin, max);
        }
    };

今日总结

回去重新把算法书捡起来

相关推荐
会员源码网28 分钟前
使用`mysql_*`废弃函数(PHP7+完全移除,导致代码无法运行)
后端·算法
木心月转码ing1 小时前
Hot100-Day10-T438T438找到字符串中所有字母异位词
算法
HelloReader2 小时前
Wi-Fi CSI 感知技术用无线信号“看见“室内的人
算法
颜酱5 小时前
二叉树分解问题思路解题模式
javascript·后端·算法
qianpeng8976 小时前
水声匹配场定位原理及实验
算法
董董灿是个攻城狮18 小时前
AI视觉连载8:传统 CV 之边缘检测
算法
AI软著研究员1 天前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish1 天前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱1 天前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
地平线开发者2 天前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶