zoukankan      html  css  js  c++  java
  • 一道关于回文的笔试题

    近日参加了一家国内某知名互联网公司的在线笔试,有一道算法题比较有意思,拿出来分享一下。

    题目:

    给定一个字符串,可以随意删除字符串里的任何字符(也可以不删除),目标是删除一些字符后让剩下的字符能够组成回文,并返回该输入字符串所能构成的最长回文长度。

    例如,输入:"eabbfa"。

    删除e和f后,构成"abba",因此返回4。

    提示:

    先看一个递归的方法:

    int recursive(string& s, int start, int end) {
        if (start == end) {
            return 1;
        }
        if (start > end) {
            return 0;
        }
        if (s[start] == s[end]) {
            return recursive(s, start + 1, end - 1) + 2;
        }
        else {
            return max(recursive(s, start, end - 1), recursive(s, start + 1, end));
        }
    }
    
    int longestPalindrom(string s) {
        return recursive(s, 0, s.length() - 1);
    }

    但是递归方法会计算许多重复子问题,导致效率下降。

    这题可以用动态规划来做。申请一个二维数组,dp[i][j],代表了字符串从 i 到 j 位置的子串中能够包含的最长回文长度。

    显然,这里的起始条件是dp[i][i] = 1,i取值为[0, s.length() - 1],因为只有一个字符的字符串一定是回文。

    之后可以用 k 代表 i 和 j 的距离,从1开始递增。

    当s[i] == s[j]时,进行状态转移,返回dp[i][j] = max(dp[i + 1][j - 1] + 2, max(dp[i + 1][j] + 1, dp[i][j - 1] + 1));

    大致思路就是这样。

    代码:

    int longestPalindrom(string s) {
        int len = s.length();
        if (len <= 1) {
            return len;
        }
        vector<vector<int>> dp(len, vector<int>(len, 0));
        int max_len = 1;
        // single character is palindrom
        for (int i = 0; i < len; ++i) {
            dp[i][i] = 1;
        }
        // k is distance between i and j
        for (int k = 1; k < len; ++k) {
            for (int i = 0; i < len - k; ++i) {
                int j = i + k;
                if (s[i] == s[j]) {
                    dp[i][j] = max(dp[i + 1][j - 1] + 2, max(dp[i + 1][j] + 1, dp[i][j - 1] + 1));
                }
                else {
                    dp[i][j] = max(dp[i + 1][j - 1], max(dp[i + 1][j], dp[i][j - 1]));
                }
            }
        }
        return dp[0][len-1];
    }
    
    int main()
    {
        string s = "rdgsaraytbbdrcdfcbsbaaoio";
        int res = longestPalindrom(s);
        return 0;
    }

    如果有更好的思路或者发现代码有纰漏,欢迎留言指正。

  • 相关阅读:
    20145204实验反思与总结
    20145204《信息安全系统设计基础》课程总结
    家庭作业:12.18,9.13,8.25,2.62
    20145204张亚军第14周博客总结
    20145204 张亚军《信息安全系统设计基础》第13周学习总结
    SLB技术原理浅析
    jumpserver在终端修改管理员密码及新建超级用户
    批量杀掉多个pid文件中记录的pid进程, 并集成到shell脚本中
    修改daemon.json重新加载后docker无法启动问题
    Docker的配置文件 daemon.json 详解
  • 原文地址:https://www.cnblogs.com/jdneo/p/5351648.html
Copyright © 2011-2022 走看看