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^4
  • s[i] 是 ‘0’ 或 ‘1’

解题思路

这道题的关键在于理解交替二进制字符串只有两种可能的模式:

  1. 以 ‘0’ 开头的模式:"010101..."
  2. 以 ‘1’ 开头的模式:"101010..."

解题思路:

我们需要分别计算将给定字符串转换为这两种模式所需的操作次数,然后取最小值。

对于每种模式,我们遍历字符串,检查每个位置上的字符是否与期望的字符匹配。如果不匹配,就需要一次操作来修改。

具体步骤:

  1. 计算转换为 “010101…” 模式所需的操作次数
  2. 计算转换为 “101010…” 模式所需的操作次数
  3. 返回两者中的最小值

优化观察: 由于交替字符串只有两种模式,如果转换为第一种模式需要 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 是字符串的长度。我们只需要遍历字符串一次来计算操作次数,使用常数额外空间。

相关题目