1529-最少的后缀翻转次数

Raphael Liu Lv10

给你一个长度为 n 、下标从 0 开始的二进制字符串 target 。你自己有另一个长度为 n 的二进制字符串 s
,最初每一位上都是 0 。你想要让 starget 相等。

在一步操作,你可以选择下标 i0 <= i < n)并翻转在 闭区间 [i, n - 1] 内的所有位。翻转意味着 '0' 变为
'1' ,而 '1' 变为 '0'

返回使 __s __ 与 __target 相等需要的最少翻转次数。

示例 1:

**输入:** target = "10111"
**输出:** 3
**解释:** 最初,s = "00000" 。
选择下标 i = 2: "00 _ **000**_ " -> "00 _ **111**_ "
选择下标 i = 0: " _ **00111**_ " -> " _ **11000**_ "
选择下标 i = 1: "1 _ **1000**_ " -> "1 _ **0111**_ "
要达成目标,需要至少 3 次翻转。

示例 2:

**输入:** target = "101"
**输出:** 3
**解释:** 最初,s = "000" 。
选择下标 i = 0: " _ **000**_ " -> " _ **111**_ "
选择下标 i = 1: "1 _ **11**_ " -> "1 _ **00**_ "
选择下标 i = 2: "10 _ **0**_ " -> "10 _ **1**_ "
要达成目标,需要至少 3 次翻转。

示例 3:

**输入:** target = "00000"
**输出:** 0
**解释:** 由于 s 已经等于目标,所以不需要任何操作

提示:

  • n == target.length
  • 1 <= n <= 105
  • target[i]'0''1'

方法一:贪心

根据翻转操作的定义,选定下标 i 之后,翻转从下标 i 到下标 n-1 的每个字符,在下标 i 前面的字符则不被翻转。因此,如果一个字符被翻转,则一定是选择了该字符的下标或者该字符前面的某个下标,然后进行了翻转操作。

初始时,所有的字符都是 0。对于下标为 0 的字符,如果其在 target 中的值是 1,则一定有一次对下标为 0 的字符的翻转操作。

对于下标为 i(i>0)的字符,如果其在 target 中的值与前一个字符(即下标为 i-1 的字符)的值不同,则一定有一次对下标为 i 的字符的翻转操作。

由此可以想到一个贪心的思路:从前往后遍历 target,对每个下标判断是否进行了翻转操作即可,同时计算最少翻转次数。

[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int minFlips(String target) {
int flips = 0;
char prev = '0';
int n = target.length();
for (int i = 0; i < n; i++) {
char curr = target.charAt(i);
if (curr != prev) {
flips++;
prev = curr;
}
}
return flips;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Solution {
public int MinFlips(string target) {
int flips = 0;
char prev = '0';
int n = target.Length;
for (int i = 0; i < n; i++) {
char curr = target[i];
if (curr != prev) {
flips++;
prev = curr;
}
}
return flips;
}
}
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int minFlips(string target) {
int flips = 0;
char prev = '0';
int n = target.size();
for (int i = 0; i < n; i++) {
char curr = target.at(i);
if (curr != prev) {
flips++;
prev = curr;
}
}
return flips;
}
};
[sol1-Python3]
1
2
3
4
5
6
7
8
class Solution:
def minFlips(self, target: str) -> int:
flips, prev = 0, "0"
for curr in target:
if curr != prev:
flips += 1
prev = curr
return flips

复杂度分析

  • 时间复杂度:O(n),其中 n 是字符串 target 的长度。遍历字符串一次。

  • 空间复杂度:O(1)。只需要维护常量的额外空间。

 Comments
On this page
1529-最少的后缀翻转次数