特殊的二进制序列
难度:
标签:
题目描述
代码结果
运行时间: 28 ms, 内存: 0.0 MB
/*
* 题目思路:
* 1. 使用流操作对字符串进行处理。
* 2. 将字符串拆分成特殊的二进制子序列。
* 3. 递归排序并合并子序列。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public String makeLargestSpecial(String S) {
if (S.length() <= 1) return S;
List<String> subs = new ArrayList<>();
int count = 0, i = 0;
for (int j = 0; j < S.length(); ++j) {
count += S.charAt(j) == '1' ? 1 : -1;
if (count == 0) {
subs.add('1' + makeLargestSpecial(S.substring(i + 1, j)) + '0');
i = j + 1;
}
}
return subs.stream()
.sorted(Collections.reverseOrder())
.collect(Collectors.joining());
}
}
解释
方法:
此题解采用的是递归分治策略。首先,它通过遍历字符串S,利用计数器count来确定特殊二进制序列的一个完整子序列(即0和1数量相等的序列)。每当count归零时,找到了一个特殊子序列。此时,该特殊子序列又以递归方式调用makeLargestSpecial来进一步分解和排序,直到不能再分解。接着,将这个子序列加上头尾的'1'和'0',将其加入结果列表res中。完成整个字符串的遍历后,对列表res中的所有序列按字典序逆序进行排序,最后合并为一个字符串作为最终结果。这个过程确保了最终的字符串是所有可能操作后的字典序最大值。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
如何确定子字符串是否满足特殊二进制序列的定义,即0和1数量相等且每个前缀中1的数量不少于0的数量?
▷🦆
在递归分治策略中,为什么能保证通过简单的逆序排序后合并就能得到字典序最大的字符串?
▷🦆
递归调用 makeLargestSpecial 函数时,为何只需处理去掉首尾'1'和'0'的中间部分,这样的处理方式是否可能丢失其他潜在的最大字典序排列?
▷相关问题
有效的括号字符串
给你一个只包含三种字符的字符串,支持的字符类型分别是 '('
、')'
和 '*'
。请你检验这个字符串是否为有效字符串,如果是有效字符串返回 true
。
有效字符串符合如下规则:
- 任何左括号
'('
必须有相应的右括号')'
。 - 任何右括号
')'
必须有相应的左括号'('
。 - 左括号
'('
必须在对应的右括号之前')'
。 '*'
可以被视为单个右括号')'
,或单个左括号'('
,或一个空字符串。- 一个空字符串也被视为有效字符串。
示例 1:
输入:s = "()" 输出:true
示例 2:
输入:s = "(*)" 输出:true
示例 3:
输入:s = "(*))" 输出:true
提示:
1 <= s.length <= 100
s[i]
为'('
、')'
或'*'