LC每日一题|20240410 - 1702. 修改后的最大二进制字符串

221 阅读3分钟

LC每日一题|20240410 - 1702. 修改后的最大二进制字符串

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

  • 操作 1 :如果二进制串包含子字符串 "00" ,你可以用 "10" 将其替换。

  • 比方说, "00010" -> "10010"

  • 操作 2 :如果二进制串包含子字符串 "10" ,你可以用 "01" 将其替换。

  • 比方说, "00010" -> "00001"

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

提示:

  • 1 <= binary.length <= 10^5
  • binary 仅包含 '0' 和 '1'

题目等级:Medium

理解题目

我们的目标是得到最大的二进制串,直觉上应该是将 0 尽可能转化为 1 ,或者将 1 尽可能前移。

再看一下题中的两个操作:

  1. 对于操作1,将 00 变成 10后,相当于凭空变出来一个 1 ,二进制串变大了,满足我们的期望。
  2. 对于操作2,将 10 变成 01后,相当于把 1 后移了,二进制串是变小的,好像并不符合我们的期望。

那操作2存在的意义是什么呢?是把 0 前移!

举个🌰

我们带入题目中给出的case: 000110

0 -- 0 -- 0 -- 1 -- 1 -- 0

1 -- 0 -- 0 -- 1 -- 1 -- 0 // 对 下标0下标1 进行 操作1

1 -- 1 -- 0 -- 1 -- 1 -- 0 // 对 下标1下标2 进行 操作1

此刻我们已经没有执行操作1的空间了。因为 下标2 处的 0 后边已经没有另一个 0可以让它执行 操作1 了。

而恰好,操作2 可以帮我们把 0 移到前边来

比如对于case 110,可以通过执行两次 操作2 将其变成 011

1 -- 1 -- 0

1 -- 0 -- 1 // 对 下标1下标2 进行 操作2

0 -- 1 -- 1 // 对 下标0下标1 进行 操作2

套入原case:

1 -- 1 -- 0 -- 0 -- 1 -- 1 // 将 下标3 处的 110 通过 操作2 变成 011

1 -- 1 -- 1 -- 0 -- 1 -- 1 // 对 下标2下标3 进行 操作1

对于 下标3 ,此时已经没有更多的 0 借来做 操作1 了,此时我们就得到了正确答案:111011

总结一下

我们可以贪心的从前向后执行 操作1 。在遇到 01 的时候利用 操作2 尝试从后边借一个 0 过来再执行 操作1 。如果借用成功,则该 01 变成 10,同时通过 操作2 借出 0 的位置变成了1;如果没有 0 可借,则证明没有其他操作空间,可直接返回。

我们可以提前保存一下0出现的位置。

AC代码

class Solution {
    fun maximumBinaryString(binary: String): String {
        val position = ArrayList<Int>()      // 0的位置
        for (i in binary.indices) if (binary[i] == '0') position.add(i)
        if (position.size <= 1) return binary     // 如果最多只有1个0,则没有操作空间,直接返回
        val ca = binary.toCharArray()
        for (i in 0 until position.size - 1) {  // 最后一个0没有其他0可借,直接退了
            ca[position[i]] = '1'               // 操作1的第0个下标变成1
            ca[position[i + 1]] = '1'           // 操作2借出0的位置变成1
            ca[position[i] + 1] = '0'           // 操作1的第1个下标变成0
            position[i + 1] = position[i] + 1   // 将操作1新生成的0保存到position中,以供下轮遍历
        }
        return ca.joinToString("")
    }
}

时间复杂度: O(N),需要两次遍历

空间复杂度: O(N),需要保存0的位置和输出结果