最短且字典序最小的美丽子字符串
难度:
标签:
题目描述
You are given a binary string s
and a positive integer k
.
A substring of s
is beautiful if the number of 1
's in it is exactly k
.
Let len
be the length of the shortest beautiful substring.
Return the lexicographically smallest beautiful substring of string s
with length equal to len
. If s
doesn't contain a beautiful substring, 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 = "100011001", k = 3 Output: "11001" Explanation: There are 7 beautiful substrings in this example: 1. The substring "100011001". 2. The substring "100011001". 3. The substring "100011001". 4. The substring "100011001". 5. The substring "100011001". 6. The substring "100011001". 7. The substring "100011001". The length of the shortest beautiful substring is 5. The lexicographically smallest beautiful substring with length 5 is the substring "11001".
Example 2:
Input: s = "1011", k = 2 Output: "11" Explanation: There are 3 beautiful substrings in this example: 1. The substring "1011". 2. The substring "1011". 3. The substring "1011". The length of the shortest beautiful substring is 2. The lexicographically smallest beautiful substring with length 2 is the substring "11".
Example 3:
Input: s = "000", k = 1 Output: "" Explanation: There are no beautiful substrings in this example.
Constraints:
1 <= s.length <= 100
1 <= k <= s.length
代码结果
运行时间: 26 ms, 内存: 15.9 MB
/*
* 思路:
* 使用Java Stream遍历字符串,筛选出包含恰好k个'1'的子字符串,
* 并在这些子字符串中找到长度最短且字典序最小的子字符串。
*/
import java.util.Comparator;
import java.util.stream.IntStream;
public class SolutionStream {
public String minBeautifulSubstring(String s, int k) {
return IntStream.range(0, s.length())
.boxed()
.flatMap(i -> IntStream.range(i + k, s.length() + 1)
.mapToObj(j -> s.substring(i, j)))
.filter(sub -> sub.chars().filter(c -> c == '1').count() == k)
.min(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
.orElse("");
}
}
解释
方法:
该解法使用了一个滑动窗口的策略来找到所有包含恰好 k 个 '1' 的子字符串。首先,定义两个指针 c (窗口左边界) 和 x (窗口右边界) 来扫描整个字符串。变量 t 用于记录当前窗口中 '1' 的数量。当 t 大于 k 时,移动左边界 c 直到 t 等于 k。随后检查左边界的 '0',若左边界是 '0' 则向右移动以找到最短的子字符串。每次当 t 等于 k 时,记录当前的子字符串。最后,在记录的所有满足条件的子字符串中找到长度最短且字典序最小的字符串返回。
时间复杂度:
O(n + m log m)
空间复杂度:
O(m * n)
代码细节讲解
🦆
如何确保处理的子字符串始终包含恰好k个'1',而不是超过k个?
▷🦆
在移动左边界以跳过开头的'0'时,为什么没有检查是否还保持有k个'1'?是否可能错过了一些有效的子字符串?
▷🦆
解法中提到当t等于k时记录子字符串,但如果这时候子字符串的开头是'0',这是否会影响到最终的子字符串长度和字典序的判断?
▷🦆
为什么在找到所有满足条件的子字符串后还需要进行一次排序?这是否影响算法的效率?
▷