LeetCode 761.特殊的二进制字符串:分治(左右括号对移动)

【LetMeFly】761.特殊的二进制字符串:分治(左右括号对移动)

力扣题目链接:https://leetcode.cn/problems/special-binary-string/

特殊的二进制字符串 是具有以下两个性质的二进制序列:

  • 0 的数量与 1 的数量相等。
  • 二进制序列的每一个前缀码中 1 的数量要大于等于 0 的数量。

给定一个特殊的二进制字符串 s。

一次移动操作包括选择字符串 s 中的两个连续的、非空的、特殊子串,并交换它们。两个字符串是连续的,如果第一个字符串的最后一个字符与第二个字符串的第一个字符的索引相差正好为 1。

返回在字符串上应用任意次操作后可能得到的字典序最大的字符串。

示例 1:

复制代码
输入: S = "11011000"
输出: "11100100"
解释:
将子串 "10" (在 s[1] 出现) 和 "1100" (在 s[3] 出现)进行交换。
这是在进行若干次操作后按字典序排列最大的结果。

示例 2:

复制代码
输入:s = "10"
输出:"10"

提示:

  • 1 <= s.length <= 50
  • s[i] 为 '0' 或 '1'。
  • s 是一个特殊的二进制字符串。

解题方法:分治

例如示例一:11011000,可以看成(()(()))。

我们要做的就是保持括号处于匹配状态下,让对应的01字符串字典序尽可能大。

匹配字符串有两种组合方式:

  1. 拼接,如() + (()) = ()(());
  2. 嵌套,在()(())外面套一个括号变成(()(()))。

这解法不就来了,我们可以反其道而行之,把``(()(()))拆成( () (()) )`:

对于最外层括号里的()和(()),当然是(())放到()前面比较好(1100放到10前面字典序更大)

这不就是天然的递归么,(()(()))只有一个"拼接的括号",外层总体顺序不变,内层()(())递归:

内层()(())有两个"拼接的括号",两个拼接的括号分别递归,直到递归字符串为空递归停止,并将两个递归完成的"拼接括号"排序重新拼接到一起,变成(())()。

  • 时间复杂度 O ( n 2 log ⁡ n ) O(n^2\log n) O(n2logn),递归像树一样,每次执行有一个排序和字符串拼接

    复制代码
    (()(()))
       |
     ()(())
     /    \
    ''    ()
  • 空间复杂度 O ( n ) O(n) O(n)

AC代码

C++
cpp 复制代码
/*
 * @LastEditTime: 2026-02-20 11:21:04
 */
/*
11011000
(()(()))
(  ()   (())    )
*/
class Solution {
private:
    vector<pair<int, int>> split(string& s) {
        vector<pair<int, int>> ans;
        int diff = 0, from = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '1') {
                diff++;
            } else {
                diff--;
            }
            if (!diff) {
                ans.push_back({from, i});
                from = i + 1;
            }
        }
        return ans;
    }
public:
    string makeLargestSpecial(string s) {
        if (s.empty()) {
            return s;
        }
        vector<pair<int, int>> pairs = split(s);
        vector<string> parts;
        parts.reserve(pairs.size());
        for (auto [l, r] : pairs) {
            parts.push_back('1' + makeLargestSpecial(s.substr(l + 1, r - l - 1)) + '0');
        }
        sort(parts.begin(), parts.end(), greater<>());
        string ans;
        for (string& part : parts) {
            ans += part;
        }
        return ans;
    }
};

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
yi01111 小时前
DAY28: LeetCode 111. 二叉树的最小深度
人工智能·笔记·python·算法·leetcode·二叉树·递归
wuyk55511 小时前
27.LeetCode 2265. 统计值等于子树平均值的节点数 —— 后序遍历实战
stm32·单片机·嵌入式硬件·算法
xiangyun6111 小时前
C++ list 模拟实现(二):const迭代器与反向迭代器,模板的黑魔法
开发语言·数据库·c++·算法·stl·list
xxwl58512 小时前
三、区域赛算法模版第三章---字符串相关算法
笔记·学习·算法
信奥卷王12 小时前
[GESP202509 六级] 划分字符串(含视频)
数据结构·算法
酒醉的胡铁12 小时前
相似度搜索的常见算法
算法·ai
局部有解12 小时前
Leetcode Hot100 - 最长连续序列
算法·leetcode·职场和发展
行者全栈架构师12 小时前
给开源 Rust 工具加一个新检查项,TRAE 帮我从想法跑到构建产物:全链路实战
前端·算法·架构
行者全栈架构师13 小时前
【鸿蒙心迹】冷启动从 2.8s 优化到 0.9s——耗时拆解与数据对比实战(HarmonyOS 7.x)
前端·算法·架构
LXY_BUAA13 小时前
《嵌入式操作系统》_framebuffer驱动_20261008
linux·运维·算法