leetcode
leetcode 2251 ~ 2300
字典序最小的美丽字符串

字典序最小的美丽字符串

难度:

标签:

题目描述

A string is beautiful if:

  • It consists of the first k letters of the English lowercase alphabet.
  • It does not contain any substring of length 2 or more which is a palindrome.

You are given a beautiful string s of length n and a positive integer k.

Return the lexicographically smallest string of length n, which is larger than s and is beautiful. If there is no such string, return an empty string.

A string a is lexicographically larger than a string b (of the same length) if in the first position where a and b differ, a has a character strictly larger than the corresponding character in b.

  • For example, "abcd" is lexicographically larger than "abcc" because the first position they differ is at the fourth character, and d is greater than c.

 

Example 1:

Input: s = "abcz", k = 26
Output: "abda"
Explanation: The string "abda" is beautiful and lexicographically larger than the string "abcz".
It can be proven that there is no string that is lexicographically larger than the string "abcz", beautiful, and lexicographically smaller than the string "abda".

Example 2:

Input: s = "dc", k = 4
Output: ""
Explanation: It can be proven that there is no string that is lexicographically larger than the string "dc" and is beautiful.

 

Constraints:

  • 1 <= n == s.length <= 105
  • 4 <= k <= 26
  • s is a beautiful string.

代码结果

运行时间: 178 ms, 内存: 18.2 MB


/*
 * 思路:
 * 使用Java Stream生成和验证美丽字符串。
 * 1. 从右向左查找可变字符。
 * 2. 使用Stream生成所有可能的字符串,找到符合条件的最小字典序。
 */

import java.util.stream.IntStream;

public class BeautifulStringStream {
    public static String nextBeautifulString(String s, int k) {
        int n = s.length();
        char[] arr = s.toCharArray();
        for (int i = n - 1; i >= 0; i--) {
            final int idx = i;
            String result = IntStream.range(arr[i] - 'a' + 1, k)
                    .mapToObj(c -> generateBeautifulString(arr, idx, (char) ('a' + c), k))
                    .filter(str -> str != null)
                    .findFirst().orElse("");
            if (!result.isEmpty()) return result;
        }
        return "";
    }

    private static String generateBeautifulString(char[] arr, int index, char newChar, int k) {
        arr[index] = newChar;
        if (isBeautiful(arr, index + 1, k)) return new String(arr);
        return null;
    }

    private static boolean isBeautiful(char[] arr, int start, int k) {
        for (int i = start; i < arr.length; i++) {
            arr[i] = 'a';
            while (i >= 1 && arr[i] == arr[i - 1]) {
                arr[i]++;
                if (arr[i] >= 'a' + k) return false;
            }
            if (i >= 2 && arr[i] == arr[i - 2]) return false;
        }
        return true;
    }

    public static void main(String[] args) {
        String s = "abcz";
        int k = 26;
        System.out.println(nextBeautifulString(s, k)); // 输出: "abda"
    }
}

解释

方法:

本题的解法使用了一种模拟进位的方式来找到大于给定字符串 s 的字典序最小的美丽字符串。首先,将字符串 s 的每个字符转换为其 ASCII 值,并从字符串的最后一个字符开始尝试递增。如果递增后的字符超过了允许的范围(前 k 个字母),则将当前字符设置为 'a' 并向前一个字符进位。在进位的过程中,每次递增后,都需要检查新的字符是否会与前一个或前两个字符形成长度为2的回文子字符串。如果形成,则继续递增当前字符。如果当前字符合法且不形成回文,则向右移动到下一个字符,并重复此过程。如果最终所有字符都处理完毕且合法,则将字符数组转换回字符串并返回。如果在字符串的第一个字符也需要进位,则返回空字符串,表示不存在符合条件的字符串。

时间复杂度:

O(nk)

空间复杂度:

O(n)

代码细节讲解

🦆
在递增字符时,你如何确保递增后的字符不会与前一个或前两个字符形成长度为2的回文子字符串?
在递增字符的过程中,每次字符值增加后,会立即检查该字符是否与其前一个字符或前两个字符相同。如果发现相同,这意味着形成了长度为2的回文子字符串,因此会继续对当前字符进行递增操作直到该字符不再形成回文。这一过程会重复进行,直至找到一个不会形成回文的字符值。
🦆
当字符递增导致需要进位时,你是如何处理连续进位的情况,特别是当存在多个连续的需要进位的字符时?
当某个字符递增后达到允许的最大值并需要进位时,该字符会被重置为'a',同时前一个字符会增加1。如果前一个字符也因此需要进位,同样的规则会被应用,即该字符也会被设置为'a',并对更前面的字符进行递增。这个连续进位的过程会一直持续到不再需要进位为止,或者到达字符串的最前端。如果最前端的字符也需要进位,则整个字符串都会重置,并在这种情况下返回空字符串。
🦆
如果在整个字符串递增过程中,某个字符已达到允许的最大ASCII值,你是如何决定它应该重置为'a'还是进行其他操作的?
当某个字符在递增过程中达到了其允许的最大ASCII值(即前k个字母的最后一个字母),该字符会被重置为'a',以保持字符仍然在允许的范围内。重置为'a'后,前一个字符会进行递增操作以实现进位。这样可以保证字符串仍然是按照字典序递增的同时,不超出允许的字符范围。
🦆
为什么在处理到第一个字符也需要进位时,就直接返回空字符串?是否有其他可能的情况需要考虑以找到有效的美丽字符串?
如果在递增过程中第一个字符也需要进位,这意味着整个字符串的所有字符都已达到允许的最大值,并且没有其他合法的更高字典序的字符串可用。在这种情况下,直接返回空字符串表示不存在更大的美丽字符串。这是因为随着每个字符的重置和最前端字符的进位,最终会导致所有可能的字符组合已经尝试过,没有剩余的有效选项。

相关问题