📜  K位第N个回文(1)

📅  最后修改于: 2023-12-03 15:17:11.204000             🧑  作者: Mango

K位第N个回文

回文是指正反读都相同的字符串,例如“level”和“racecar”就是回文。在这里,我们来探讨在给定字符集中,第K位的第N个回文的情况。

解题思路

对于回文的构成,我们可以将其分为两个部分:左半部分和右半部分,它们在回文中是对称的。假设字符集的大小为M,那么左半边有M^((K+1)/2)种选择,右半边有M^(K/2)种选择,即总共有M^((K+1)/2) * M^(K/2)种回文。

我们可以通过递归来实现生成回文的过程,每次递归中处理左半边和右半边的情况。具体地,我们先递归到左半边,生成前一半的回文,然后再递归到右半边,生成后一半的回文。当K为奇数时,中间元素可以任意选择字符集中的一个字符。

生成回文的过程是一个深度优先搜索的过程,当找到第N个回文时,直接返回。

代码实现

具体实现可以参考下面的C++代码片段:

class Solution {
public:
    string kthPalindrome(int k, int n, string& s) {
        int M = s.size();
        int half = (k + 1) / 2;
        long long num = pow(M, half); // 左半部分的方案数
        if (n > num * pow(M, k - half)) return ""; // 如果所求的回文不合法,返回空串
        string left = "", right = "";
        if (k % 2 == 1) { // K为奇数
            for (int i = 0; i < M; i++) {
                string tmp = s.substr(i, 1); // 中间字符
                dfs(k, n, s, left + tmp, right, num); // 生成回文
                if (ans != "") return ans;
            }
        } else { // K为偶数
            dfs(k, n, s, left, right, num); // 生成回文
        }
        return ans;
    }
private:
    string ans = ""; // 存储所求的回文字符串
    void dfs(int k, int& n, string& s, string left, string right, long long num) {
        if (left.size() + right.size() == k) { // 生成完整回文
            if (--n == 0) ans = left + right; // 找到第N个回文,将其存储在ans中
            return;
        }
        for (int i = 0; i < s.size(); i++) { // 枚举字符集中的每个字符
            if (left.size() + right.size() + 2 > k) break; // 如果回文长度已经大于K,退出
            string tmp = s.substr(i, 1);
            if (left + tmp <= right) continue; // 构成回文时必须保证左右对称
            if (left.size() + right.size() + 2 == k && tmp > s.substr(0, 1)) break; // 如果左半边以最小字符开始,那么右半边不能用更小的字符
            if (left.size() + 1 == half && tmp > s.substr(0, 1)) break; // 如果左半部分已经是最小的,那么可以任选右半边的字符
            if (left.size() < half) dfs(k, n, s, left + tmp, right + tmp, num / M); // 递归到左半部分
            else dfs(k, n, s, left, tmp + right, num / M); // 递归到右半部分
            if (!ans.empty()) return;
        }
    }
};
算法复杂度

由于每个字符都需要进行M次枚举,因此算法的时间复杂度是O(M^K)(这里不考虑第N个回文不合法的情况)。由于递归树的深度最多为K/2,因此算法的空间复杂度也是O(K)。