[Leetcode] 761. Special Binary String 解题报告

本文介绍Leetcode 761题的解题报告,讨论如何构造特殊二进制字符串以达到最大字典序。通过分解、排序和重组特殊子串,利用括号对的类比辅助理解解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Special binary strings are binary strings with the following two properties:

The number of 0's is equal to the number of 1's.Every prefix of the binary string has at least as many 1's as 0's.

Given a special string S, a move consists of choosing two consecutive, non-empty, special substrings of S, and swapping them. (Two strings are consecutive if the last character of the first string is exactly one index before the first character of the second string.)

At the end of any number of moves, what is the lexicographically largest resulting string possible?

Example 1:

Input: S = "11011000"
Output: "11100100"
Explanation:
The strings "10" [occuring at S[1]] and "1100" [at S[3]] are swapped.
This is the lexicographically largest string possible after some number of swaps.

Note:

  1. S has length at most 50.
  2. S is guaranteed to be a special binary string as defined above.

思路

一道比较难的题目了,总体来讲分为四个步骤:1)将S分解为尽可能多的special strings;2)让每个special string以1开头,并且以0结尾,然后采用递归对中间部分进行同样的处理;3)对所有已经分解出来的special strings进行排序;4)将排好序的special strings连接起来,就形成了最终的结果。

为什么这么做是对的呢?在我们的例子里面,假设我们遇到一个1M0是special string,那么在我们的处理过程中,M作为1M0的中间部分也一定是另外一个special string。这是因为:1)M中的1和0的个数相同;2)如果在M中有一个前缀P,其中1的个数比0的个数少一个,那么1P就一定是一个special string;否则1P就会成为一个special string,在1M0之前会被找出来。所以M中的每个前缀中,1的数量都不比0少。

处理完了每个special string,然后将它们按照从大到小的顺序连接起来,就一定是题目所求。

------------------------------------------------------------------------------------------------------------------------------

上面的解释其实写的很不清楚,我自己也没有完全理解。后来我在网上看到一个很好的类比:就是把这个题目比作合法的括弧对,我们可以把‘1’映射到‘(’,把'0'映射到'0',这样一组合法的括弧对其实也就意味着一串合法的special string:1)合法的括弧堆中,‘(’和')‘的个数一定是相同的;2)合法括弧对的任意一个前缀中,'('的出现次数都不会少于')'。

如果在一个串中,我们定义所有没有嵌套关系的括弧对都属于同一级,而在一个括弧对之内的同级括弧对都更低一节,那么通过观察可知,在同一级括弧对中,嵌套越深的括弧对越需要靠前,因此我们的解法就是:首先将同级的括弧对都找出来,并且分别递归处理,使其对应于LargestSpecialString,然后将这些括弧对再进行降序排列,结果就是LargestSpecialString对应的括弧对。

示例中给出的11011000就相当于(()(()))。我们在本级它只有一个括弧对,而它的下一级则有两个,即()和(()),显然第二个嵌套更深,所以两个更换位置,形成(())(),再加上原来最外层的括弧对,就形成了((())()),这不就对应着11011000的最终结果11100100吗?

代码

class Solution {
public:
    string makeLargestSpecial(string S) {
        int count = 0, i = 0;
        vector<string> res;
        for (int j = 0; j < S.size(); ++j) {
          if (S[j] == '1') {
              ++count;
          }
          else {
              --count;
          }
          if (count == 0) {
            res.push_back('1' + makeLargestSpecial(S.substr(i + 1, j - i - 1)) + '0');
            i = j + 1;
          }
        }
        sort(res.begin(), res.end(), greater<string>());
        string res2 = "";
        for (int i = 0; i < res.size(); ++i) {
            res2 += res[i];
        }
        return res2;
    }
};


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值