Easy
题目描述
给你一个仅由字符 ‘0’ 和 ‘1’ 组成的字符串 s 。一次 操作 中,你可以将任何一个 ‘0’ 变成 ‘1’ ,或者将 ‘1’ 变成 ‘0’ 。
交替字符串 是一个相邻字符都不相同的字符串。例如,字符串 "010" 是交替字符串,而字符串 "0100" 不是。
返回使 s 变成 交替字符串 所需的 最少 操作数。
示例 1:
输入:s = "0100"
输出:1
解释:如果将最后一个字符变为 '1' ,s 就变成 "0101" ,即符合交替字符串定义。
示例 2:
输入:s = "10"
输出:0
解释:s 已经是交替字符串。
示例 3:
输入:s = "1111"
输出:2
解释:需要 2 步操作得到 "0101" 或者 "1010" 。
提示:
1 <= s.length <= 10^4s[i]是 ‘0’ 或 ‘1’
解题思路
这道题的关键在于理解交替二进制字符串只有两种可能的模式:
- 以 ‘0’ 开头的模式:
"010101..." - 以 ‘1’ 开头的模式:
"101010..."
解题思路:
我们需要分别计算将给定字符串转换为这两种模式所需的操作次数,然后取最小值。
对于每种模式,我们遍历字符串,检查每个位置上的字符是否与期望的字符匹配。如果不匹配,就需要一次操作来修改。
具体步骤:
- 计算转换为 “010101…” 模式所需的操作次数
- 计算转换为 “101010…” 模式所需的操作次数
- 返回两者中的最小值
优化观察: 由于交替字符串只有两种模式,如果转换为第一种模式需要 k 次操作,那么转换为第二种模式一定需要 n - k 次操作(其中 n 是字符串长度)。因此我们只需要计算一种模式的操作次数,另一种可以直接得出。
代码实现
class Solution {
public:
int minOperations(string s) {
int n = s.length();
int count0 = 0; // 转换为 "010101..." 的操作次数
for (int i = 0; i < n; i++) {
// 偶数位置应该是 '0',奇数位置应该是 '1'
char expected = (i % 2 == 0) ? '0' : '1';
if (s[i] != expected) {
count0++;
}
}
// 转换为 "101010..." 的操作次数
int count1 = n - count0;
return min(count0, count1);
}
};
class Solution:
def minOperations(self, s: str) -> int:
n = len(s)
count0 = 0 # 转换为 "010101..." 的操作次数
for i in range(n):
# 偶数位置应该是 '0',奇数位置应该是 '1'
expected = '0' if i % 2 == 0 else '1'
if s[i] != expected:
count0 += 1
# 转换为 "101010..." 的操作次数
count1 = n - count0
return min(count0, count1)
public class Solution {
public int MinOperations(string s) {
int n = s.Length;
int count0 = 0; // 转换为 "010101..." 的操作次数
for (int i = 0; i < n; i++) {
// 偶数位置应该是 '0',奇数位置应该是 '1'
char expected = (i % 2 == 0) ? '0' : '1';
if (s[i] != expected) {
count0++;
}
}
// 转换为 "101010..." 的操作次数
int count1 = n - count0;
return Math.Min(count0, count1);
}
}
/**
* @param {string} s
* @return {number}
*/
var minOperations = function(s) {
let changes1 = 0; // changes needed to make pattern "010101..."
let changes2 = 0; // changes needed to make pattern "101010..."
for (let i = 0; i < s.length; i++) {
if (i % 2 === 0) {
// even index
if (s[i] !== '0') changes1++;
if (s[i] !== '1') changes2++;
} else {
// odd index
if (s[i] !== '1') changes1++;
if (s[i] !== '0') changes2++;
}
}
return Math.min(changes1, changes2);
};
复杂度分析
| 复杂度类型 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 时间复杂度 | O(n) | O(1) |
| 空间复杂度 | O(1) | O(1) |
其中 n 是字符串的长度。我们只需要遍历字符串一次来计算操作次数,使用常数额外空间。