leetcode
leetcode 651 ~ 700
特殊的二进制序列

特殊的二进制序列

难度:

标签:

题目描述

代码结果

运行时间: 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的数量?
通过遍历子字符串并维护一个计数器来确定是否满足条件。初始计数器为0,遍历字符串中的每个字符,遇到'1'则计数器加1,遇到'0'则计数器减1。如果在任何时刻计数器变为负,则说明存在一个前缀其中0的数量多于1的数量,此时子字符串不满足条件。只有当遍历结束时计数器恢复为0,且在整个遍历过程中计数器没有变为负,才能确定该子字符串满足特殊二进制序列的定义。
🦆
在递归分治策略中,为什么能保证通过简单的逆序排序后合并就能得到字典序最大的字符串?
在递归分治策略中,每找到一个满足条件的特殊子序列,都会进行递归处理以确保子序列自身是最大的字典序。处理完所有子序列后,将它们逆序排序的原因是,更大的子序列如果排在前面,会使得合并后的整体字典序更大。这是因为在字典序排序中,字符串的开始部分权重更大。因此,通过将最大的子序列放在最前面,然后依次降序排列,确保了整体字符串在字典序上尽可能大。
🦆
递归调用 makeLargestSpecial 函数时,为何只需处理去掉首尾'1'和'0'的中间部分,这样的处理方式是否可能丢失其他潜在的最大字典序排列?
递归处理去掉首尾'1'和'0'的中间部分是因为,根据题目的定义,一个特殊的二进制序列必须以'1'开头,以'0'结尾,且内部的子序列也须满足特殊二进制序列的要求。因此,首尾的'1'和'0'是固定的,只需要递归处理中间部分以确定如何使这部分达到最大字典序。这种处理方式不会丢失潜在的最大字典序排列,因为任何更大的排列也必须符合特殊二进制序列的定义,即以'1'开头和'0'结尾,且内部满足特殊序列的要求。

相关问题

有效的括号字符串

给你一个只包含三种字符的字符串,支持的字符类型分别是 '('')''*'。请你检验这个字符串是否为有效字符串,如果是有效字符串返回 true

有效字符串符合如下规则:

  • 任何左括号 '(' 必须有相应的右括号 ')'
  • 任何右括号 ')' 必须有相应的左括号 '(' 。
  • 左括号 '(' 必须在对应的右括号之前 ')'
  • '*' 可以被视为单个右括号 ')' ,或单个左括号 '(' ,或一个空字符串。
  • 一个空字符串也被视为有效字符串。

 

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "(*)"
输出:true

示例 3:

输入:s = "(*))"
输出:true

 

提示:

  • 1 <= s.length <= 100
  • s[i]'('')''*'