力扣 leetcode 1758. 生成交替二进制字符串的最少操作数

问题描述

给你一个仅由字符 '0''1' 组成的字符串 s 。一步操作中,你可以将任一 '0' 变成 '1' ,或者将 '1' 变成 '0'

交替字符串 定义为:如果字符串中不存在相邻两个字符相等的情况,那么该字符串就是交替字符串。例如,字符串 "010" 是交替字符串,而字符串 "0100" 不是。

返回使 s 变成 交替字符串 所需的 最少 操作数。

提示:

  • 1 <= s.length <= 10^4
  • s[i] 是 '0' 或 '1'

示例

示例 1:

输入:s = "0100"
输出:1
解释:如果将最后一个字符变为 '1' ,s 就变成 "0101" ,即符合交替字符串定义。

示例 2:

输入:s = "10"
输出:0
解释:s 已经是交替字符串。

示例 3:

输入:s = "1111"
输出:2
解释:需要 2 步操作得到 "0101" 或 "1010" 。

解题思路

这道题要做的是判断字符串相邻字符相同的个数,但是需要考虑的是可能某个字符替换之后,也会对后续的结果产生影响,例如, s="000",将下标 1 处的 '0' 替换为 '1' 之后,就组成了交替字符。

另外,还存在 s="1101" 的情况,如果我们先判断 s[1] == s[0] ,并将 s[1] 替换为 '0' ,就需要再替换 s[2]s[3] ,共替换 3 次。 而实际上的最小替换次数为 1 次,即将 s[0] 替换即可。在这种情况下,我们不需要重新考虑,我们可以发现, 3+1=4 ,而 4 是字符串的长度。这是因为这两种替换后的字符串互补, 第一种替换结果是 "1010" ,第二种替换结果是 "0101"。因此,我们只需计算一次替换次数,然后选择 min(cnt, s.length() - cnt) 即可。 代码如下:

class Solution {
public:
    int minOperations(string s) {
        int cnt = 0;
        bool replace = false; // 我们不对字符串进行修改,而是用一个遍历记录上一个字符是否已经修改过了
        for(int i = 1; i < s.size(); i++){
            if(s[i] == s[i - 1] && !replace){
                cnt++;
                replace = true;
            }
            else if(s[i] != s[i - 1] && replace){
                cnt++;
            }
            else if(s[i] == s[i - 1] && replace){
                replace = false;
            }
        }
        cnt = (cnt + cnt) < s.size() ? cnt : (s.size() - cnt);
        return cnt;
    }
};

提交代码时,这里的 if-else 判断的次序对时间影响很大。

posted @ 2022-11-29 19:33  greatestchen  阅读(18)  评论(0编辑  收藏  举报