字典序最小的美丽字符串
难度:
标签:
题目描述
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, andd
is greater thanc
.
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的回文子字符串?
▷🦆
当字符递增导致需要进位时,你是如何处理连续进位的情况,特别是当存在多个连续的需要进位的字符时?
▷🦆
如果在整个字符串递增过程中,某个字符已达到允许的最大ASCII值,你是如何决定它应该重置为'a'还是进行其他操作的?
▷🦆
为什么在处理到第一个字符也需要进位时,就直接返回空字符串?是否有其他可能的情况需要考虑以找到有效的美丽字符串?
▷