1529. 最少的后缀翻转次数
题目描述
给你一个长度为 n 、下标从 0 开始的二进制字符串 target 。你自己有另一个长度为 n 的二进制字符串 s ,最初每一位上都是 0 。你想要让 s 和 target 相等。
在一步操作,你可以选择下标 i(0 <= i < n)并翻转在 闭区间 [i, n - 1] 内的所有位。翻转意味着 '0' 变为 '1' ,而 '1' 变为 '0' 。
返回使 s 与 target 相等需要的最少翻转次数。
示例 1:
输入:target = "10111" 输出:3 解释:最初,s = "00000" 。 选择下标 i = 2: "00000" -> "00111" 选择下标 i = 0: "00111" -> "11000" 选择下标 i = 1: "11000" -> "10111" 要达成目标,需要至少 3 次翻转。
示例 2:
输入:target = "101" 输出:3 解释:最初,s = "000" 。 选择下标 i = 0: "000" -> "111" 选择下标 i = 1: "111" -> "100" 选择下标 i = 2: "100" -> "101" 要达成目标,需要至少 3 次翻转。
示例 3:
输入:target = "00000" 输出:0 解释:由于 s 已经等于目标,所以不需要任何操作
提示:
n == target.length1 <= n <= 105target[i]为'0'或'1'
解法
方法一:贪心
思考
操作是翻转某个后缀,要把全 \(0\) 变成 \(target\)。\(n\le 10^5\),不能对每个后缀模拟。当前缀已经与 \(target\) 一致时,下一次翻转只应发生在下一个与当前状态不同的位置。
从左到右扫描:翻转次数的奇偶决定该位当前值。若与 \(target[i]\) 不同,必须在 \(i\) 处再翻一次后缀。这样每次翻转都修正在此之前无法改写的最左错误位,次数最少。
我们从左到右遍历字符串 \(\textit{target}\),用变量 \(\textit{ans}\) 记录翻转次数。 当遍历到下标 \(i\) 时,如果当前的翻转次数 \(\textit{ans}\) 的奇偶性与 \(\textit{target}[i]\) 不同,则需要在下标 \(i\) 处进行一次翻转操作,将 \(\textit{ans}\) 加 \(1\)。
时间复杂度 \(O(n)\),其中 \(n\) 是字符串的长度。空间复杂度 \(O(1)\)。
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |