问题描述
给你一个仅由字符 '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
判断的次序对时间影响很大。