📌  相关文章
📜  使用所有字母表的前 K 个字母且没有两个相邻字符相同的字典最小字符串(1)

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

使用所有字母表的前 K 个字母且没有两个相邻字符相同的字典最小字符串

本题目要求生成一个字符长度为 n 的字符串,该字符串由字母表前 K 个字符组成,且相邻字符不能相同。要求生成的是字典序最小的字符串。

思路

我们可以对于每个位置选择字母表中最小的可选字符,这种贪心策略可以保证字典序最小。但是我们不能简单相信这一策略是正确的,因为它涉及到了相邻字符的限制。所以我们需要根据每次选择的字符,来调整可以选择的字符集。具体来说,我们可以每次选择顺序的第一个可选字符,在选择后,将其从下一次的可选字符集中删除。这样,我们可以保证每次选择的字符是当前可选字符集中字典序最小的字符。同时我们可以保证当前选择是不会影响以后选择的,因为我们每次删除的是下一次选择所处的位置的可能性,而当前选择的是上一次选定位置的可选最小字符。

代码实现

下面是 Java 代码实现,时间复杂度为 O(nk),其中 n 是字符串长度,k 是字符集大小。

public static String getMinString(int k, int n) {
    // 初始化可选字符集,将所有字符都加入集合中
    Set<Character> candidates = new HashSet<>();
    for (int i = 0; i < k; i++) {
        candidates.add((char)('a' + i));
    }
    StringBuilder sb = new StringBuilder();
    // 每次选择可选字符集合中字典序最小的字符
    for (int i = 0; i < n; i++) {
        // 找到当前可选字符集合中字典序最小的字符
        char minChar = candidates.iterator().next();
        // 将当前字符加入最终字符串中
        sb.append(minChar);
        // 调整可选字符集合,并删除已经选择的字符
        candidates.remove(minChar);
        if (i < n - 1) {
            // 更新可选字符集合
            char preChar = sb.charAt(i);
            if (preChar != 'a') {
                candidates.add((char)(preChar - 1));
            }
            if (minChar != 'a') {
                candidates.add((char)(minChar - 1));
            }
        }
    }
    return sb.toString();
}
总结

本题利用了贪心策略保证了字典序最小,具体的可选字符集合调整确保了字符间相邻限制的满足。