跳过正文
  1. leetcode 题解/

1702_修改后的最大二进制字符串

·235 字·2 分钟
目录

题目
#

给你一个二进制字符串 binary ,它仅有 0 或者 1 组成。你可以使用下面的操作任意次对它进行修改:

  • 操作 1 :如果二进制串包含子字符串 "00" ,你可以用 "10" 将其替换。
    • 比方说, "**00**010" -> "**10**010"
  • 操作 2 :如果二进制串包含子字符串 "10" ,你可以用 "01" 将其替换。
    • 比方说, "000**10**" -> "000**01**"

请你返回执行上述操作任意次以后能得到的 最大二进制字符串 。如果二进制字符串 x 对应的十进制数字大于二进制字符串 y 对应的十进制数字,那么我们称二进制字符串 **x **大于二进制字符串 **y **。

示例 1:

输入:binary = "000110"
输出:"111011"
解释:一个可行的转换为:
"000110" -> "000101"
"000101" -> "100101"
"100101" -> "110101"
"110101" -> "110011"
"110011" -> "111011"

示例 2:

输入:binary = "01"
输出:"01"
解释:"01" 没办法进行任何转换。

解法
#

此题的数据量很大(10^5), 必须找到线性复杂度的方法才能解决。

我们从左往右地逐一处理,一开始我们只考虑前两个字符,然后逐步往尾部增加字符来考虑。分析情况之后,我们会发现,该问题的局部最优解即是全局最优解,即我们可以用贪心法来解决。

我们只需考虑尾部两个字符的情况:

  • 00: 转换为 10
  • 10: 如果前面还存在 0, 比如 xxx01110, 则我们可以通过连续转换(10->01)得到 xxx10111
  • 11: 保持不变
  • 01: 保持不变

由于字符串在 python 中是不可直接修改的,使用字符串拼接的开销也很大,我们可以用列表来存储字符,最后在将其拼接成字符串,但是可惜这个操作仍然会超时。

观察规律,我们会发现,由以上四种操作后,我们的结果字符串中最多只出现一个 0。因而我们唯一需要保存的就是这个 0 出现的位置。

还有一种直观的思维方式:

通过操作 10->01, 我们可以把所有的 1 都放到低位,所有的 0 都放到高位。

通过操作 00->10, 我们可以把高位连续的 00000 变成 11110

代码
#

class Solution:
    def maximumBinaryString(self, binary: str) -> str:
        if len(binary) < 2:
            return binary

        ans = [binary[0], binary[1]]
        if ans == ['0', '0']:
            ans = ['1', '0']
        idx0 = 0 if ans[0] == '0' else -1
        
        lastChr = ans[-1]
        for i in range(2, len(binary)):
            c = binary[i]
            if lastChr + c == '01':
                idx0 = i - 1
                lastChr = '1'
            elif lastChr + c == '00':
                lastChr = '0'
            elif lastChr + c == '10':
                if idx0 > -1:
                    idx0 += 1
                    lastChr = '1'
                else:
                    lastChr = '0'
            else:
                lastChr = '1'
        
        return '1' * (len(binary) - 1) + lastChr if idx0 < 0 else '1' * idx0 + '0' + '1' * (len(binary) - idx0 - 1)