LeetCode 761. 特殊的二进制字符串

LeetCode 761. 特殊的二进制字符串

题目描述

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

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

给定一个特殊的二进制序列 S,我们可以将其中任意相邻的两个 特殊子串 进行交换(这两个子串本身也是特殊串)。通过任意次这样的交换,求出所能得到的字典序最大的结果。

题目理解

这种特殊的二进制序列与有效的括号序列非常相似:把 1 看作左括号 (,把 0 看作右括号 ),则满足括号匹配的序列就是特殊串。例如 "1100" 对应 (())"10" 对应 ()。多个特殊串可以并列,如 "1010" 对应 ()()

题目允许交换任意两个 相邻的、并列的 特殊子串,目标是通过交换使得整个串的字典序最大。注意交换只能在并列的同一层子串之间进行,不能跨层交换。但是通过递归处理,我们可以让每一层内部达到最大,从而整体达到最大。

解题思路

本题的核心解法是 递归分解 + 排序

  1. 分解:遍历原串,用计数器 cnt 记录 10 的差值(1 加 1,0 减 1)。每当 cnt 归零,说明找到了一个完整的特殊子串(它一定以 1 开头、以 0 结尾)。将这些一级子串拆出来。
  2. 递归:对每个一级子串,去掉首尾的 10,其内部仍是一个特殊串(可能为空或更小的特殊串),递归调用函数处理内部,使其达到最大字典序,然后再重新加上首尾的 10
  3. 排序:得到当前层的所有一级子串(每个都已经内部最优)后,将它们按 a + b > b + a 的规则降序排序,这样拼接后就能使当前层整体字典序最大。
  4. 拼接:将排序后的子串连接起来,返回结果。

算法步骤

  1. 如果 S 长度 ≤ 2,直接返回 S(特殊串只有可能是 "10" 或空串)。
  2. 初始化一个空的字符串列表 q 用于存放一级子串,临时字符串 s 用于累积当前子串,计数器 cnt = 0
  3. 遍历 S 的每个字符 c
    • c 加入 s
    • c == '1'cnt++;否则 cnt--
    • cnt == 0 时,说明从上一个 cnt 归零点(或开头)到当前位置形成了一个一级特殊子串。
      • 取出 s 的内部部分(去掉首尾),递归调用 makeLargestSpecial 得到内部最大串。
      • 在外层重新包裹 '1''0',形成新的串,加入 q
      • 清空 s,准备处理下一个并列子串。
  4. q 中的字符串按照 a + b > b + a 的规则排序(即比较两种拼接方式的字典序,大的在前)。
  5. 将排序后的所有字符串拼接成最终结果 res,返回。

代码实现(C++)

classSolution{public: string makeLargestSpecial(string S){if(S.size()<=2)return S;// 基础情况 vector<string> sub;// 存储一级子串 string cur;int cnt =0;for(char c : S){ cur += c;if(c =='1') cnt++;else{ cnt--;if(cnt ==0){// 找到一个一级子串// 递归处理内部(去掉首尾的1和0) string inner =makeLargestSpecial(cur.substr(1, cur.size()-2)); sub.push_back('1'+ inner +'0');// 重新包裹 cur.clear();}}}// 将一级子串按字典序最大的方式排序sort(sub.begin(), sub.end(),[](const string& a,const string& b){return a + b > b + a;});// 拼接 string ans;for(string& s : sub) ans += s;return ans;}};

代码解释

  • 基础情况:当长度 ≤ 2 时,特殊串只能是 "10"(或空串),无需进一步处理。
  • 计数器 cnt:用于识别一级特殊子串。当 cnt 从 0 开始,经过若干字符后再次变为 0,这一段就是一级子串。这类似于括号匹配中找到一个完整的括号对。
  • 递归处理内部:一级子串去掉首尾 '1''0' 后,内部可能包含多个并列的特殊子串(例如 "1100" 去掉首尾得 "10""11011000" 去掉首尾得 "101100"),这些内部子串也需要达到最大字典序,所以递归调用。
  • 排序规则:对于两个并列的子串 ab,要使得最终拼接最大,需要比较 a+bb+a 的字典序,选择更大的拼接方式。这种比较具有传递性,可以确保排序后整体最大(类似于 LeetCode 179 最大数问题)。
  • 重新包裹:内部处理完后,再套上 '1''0',这样当前层的一级子串已经内部最优。

举例演示

S = "11011000" 为例:

  • 遍历过程:
    • 读入 1,cnt=1,cur="1"
    • 读入 1,cnt=2,cur="11"
    • 读入 0,cnt=1,cur="110"
    • 读入 1,cnt=2,cur="1101"
    • 读入 1,cnt=3,cur="11011"
    • 读入 0,cnt=2,cur="110110"
    • 读入 0,cnt=1,cur="1101100"
    • 读入 0,cnt=0,此时 cur="11011000",是一个一级子串。
      • 内部部分:cur.substr(1, 6) = "101100"
      • 递归处理 "101100"
        • 遍历 "101100"
          • 1 -> cnt=1, cur="1"
          • 0 -> cnt=0, cur="10",找到一级子串。内部部分 "" 递归返回 "",包裹后得 "10",加入 sub1。
          • 继续 1 -> cnt=1, cur="1"
          • 1 -> cnt=2, cur="11"
          • 0 -> cnt=1, cur="110"
          • 0 -> cnt=0, cur="1100",找到一级子串。内部部分 "10" 递归返回 "10"(因为长度 2),包裹后得 "1100",加入 sub1。
        • sub1 = ["10","1100"]。排序比较:
          • "10"+"1100" = "101100""1100"+"10" = "110010""110010" 更大,所以排序后为 ["1100","10"]
        • 递归返回 "110010"
      • 外层包裹 '1' + "110010" + '0'"11100100"
      • "11100100" 加入 sub(此时只有这一个子串)。
  • 排序(只有一个)后直接拼接,结果为 "11100100"

通过手动验证,"11011000" 的最大特殊串确实是 "11100100"

复杂度分析

  • 时间复杂度:每个字符在递归的每一层都会被访问一次,递归深度为特殊串的嵌套层数,最坏情况下为 O(n)。排序操作在最坏情况下,每一层可能需要排序,总时间复杂度约为 O(n log n)。实际上,由于递归和排序的综合,整体时间复杂度为 O(n2) ?更精确的分析:每个字符被处理多次,但每次递归都会减少问题规模,排序的字符串总长度和为 n,每次排序的复杂度与字符串长度相关。可以粗略估计为 O(n2) 但在数据范围内足够。LeetCode 官方题解给出的是 O(n2) 级别。
  • 空间复杂度:递归调用栈深度 O(n),加上存储临时字符串,总空间复杂度 O(n)。

总结

  • 本题的关键在于将特殊串与括号序列联系起来,利用计数器分解出并列的子串。
  • 递归处理内部,保证子问题最优。
  • 排序规则 a+b > b+a 巧妙地解决了并列子串的排列问题,使得最终字典序最大。
  • 该解法既清晰又高效,是处理此类问题的经典思路。

Read more

Godot被AI代码“围攻”!维护者崩溃发声:“不知道还能坚持多久”

Godot被AI代码“围攻”!维护者崩溃发声:“不知道还能坚持多久”

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 当大模型能在几秒钟内生成一段“看起来像那么回事”的补丁时,开源社区却开始付出另一种代价。 最近,开源游戏引擎 Godot 的核心维护团队公开吐槽:他们正被大量“AI 生成的低质量代码”淹没。那些代码往往结构完整、注释齐全、描述洋洋洒洒,但真正的问题是——提交者可能并不理解自己交上来的内容。 这件事,并不是简单的“有人偷懒用 AI 写代码”。它正在触及开源协作最核心的东西:信任。 一场悄无声息的“AI 洪水” 事情的导火索来自一条 Bluesky 讨论帖。 Godot 主要维护者之一、同时也是 Godot 商业支持公司 W4 Games 联合创始人的 Rémi Verschelde 表示,所谓的“AI slop”

By Ne0inhk
诺奖得主辛顿最新访谈:1 万个 AI 可以瞬间共享同一份“灵魂”,这就是为什么人类注定被超越

诺奖得主辛顿最新访谈:1 万个 AI 可以瞬间共享同一份“灵魂”,这就是为什么人类注定被超越

当宇宙级的“嘴炮”遇到降维打击。 编译 | 王启隆 来源 | youtu.be/l6ZcFa8pybE 出品丨AI 科技大本营(ID:rgznai100) 打开最新一期知名播客 StarTalk 的 YouTube 评论区,最高赞的一条留言是这样写的: “我长这么大,第一次看到尼尔·德葛司·泰森(Neil deGrasse Tyson)在一档节目里几乎全程闭嘴,像个手足无措的小学生一样乖乖听讲。” 作为全美最知名的天体物理学家,泰森平时的画风是充满激情、喋喋不休、用宇宙的宏大来震撼嘉宾。但这一次,坐在他对面的那位满头银发、带着温和英音的英国老人,仅仅用最平淡的语气,就让整个演播室陷入了数次令人窒息的沉默。 这位老人是 Geoffrey Hinton。深度学习三巨头之一,2024 年诺贝尔物理学奖得主,被公认为“AI 教父”。 对经常阅读 Hinton 演讲的我来说,这也是比较新奇的一幕—

By Ne0inhk
48小时“烧光”56万!三人创业团队濒临破产,仅因Gemini API密钥被盗:“AI账单远超我们的银行余额”

48小时“烧光”56万!三人创业团队濒临破产,仅因Gemini API密钥被盗:“AI账单远超我们的银行余额”

整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 「仅过了 48 小时,一笔 8.2 万美元的天价费用凭空出现,较这家小型初创公司的正常月费暴涨近 46000%。」 这不是假设的虚幻故事,而是一家墨西哥初创公司正在经历的真实危机。 近日,一位名为 RatonVaquero 的开发者在 Reddit 发帖求助称,由于他的 Gemini API 密钥被盗用,原本每月仅约 180 美元(约 1242 元)的费用,在短短 48 小时内暴涨到 82,314.44 美元(约 56.8 万元)。对于这家只有三名开发者的小型创业团队来说,这笔突如其来的账单,几乎等同于灭顶之灾。 “我现在整个人都处在震惊和恐慌之中。”RatonVaquero

By Ne0inhk
假网站排全网第二,真官网翻五页都找不到!NanoClaw创始人破防:SEO之战,我快要输了

假网站排全网第二,真官网翻五页都找不到!NanoClaw创始人破防:SEO之战,我快要输了

整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 自从 OpenClaw 爆火之后,各种“Claw”项目接连出现,其中以安全优化版 NanoClaw 最为知名。它的核心代码仅有 4000 行,却获得了 AI 大牛 Andrej Karpathy 的点赞。 可谁也没想到,这款口碑极佳的开源项目,近来竟被一个仿冒网站抢了风头。 投诉无门之下,NanoClaw 创始人 Gavriel Cohen 在 X 社交平台上无奈发文怒斥:谷歌搜索错误地将假网站排在真官网前面,不仅破坏了项目声誉,还埋下了严重的安全隐患,而他费尽心力,却只能哀叹一句——“我正在为自己的开源项目打 SEO 战,但我快要输了。” 那么,NanoClaw 究竟发生了什么?又是怎么走红的?事情还要从 OpenClaw

By Ne0inhk