给你一个字符串 s ,它仅包含字符 'a' 和 'b' 。
你可以删除 s 中任意数目的字符,使得 s 平衡 。当不存在下标对 (i,j) 满足 i < j ,且 s[i] = 'b' 的同时 s[j]= 'a' ,此时认为 s 是 平衡 的。
请你返回使 s 平衡 的 最少 删除次数。
输入:s = "aababbab"
输出:2
解释:你可以选择以下任意一种方案:
下标从 0 开始,删除第 2 和第 6 个字符("aababbab" -> "aaabbb"),
下标从 0 开始,删除第 3 和第 6 个字符("aababbab" -> "aabbbb")。
这道题简单来说 就是将字符串转换成左边全是a,右边全是b,最少需要多少步。
拿到手之后,没有多少思路,即使理解了题目是要求,但是却想不到怎么去解决这个问题。
查看了一些资料之后,得到一个思路,以一个字符为基准,将基准左侧的b去掉,基准右侧的a去掉,这样就得到了想要的结果。
于是立刻开始双重循环,伪代码如下:
int min = Max
for(i...) {
int count = 0;
for(j = 0; j < i) {
// 获取左侧b的数量
count++
}
for(j= i + 1;j < length) {
// 获取右侧a的数量
count++
}
min = Math.min(min, count)
}
结果运行之后,超时了,可以看出这道题不仅思路比较难想,对复杂度也有要求。
只能再找资料优化,得到新的思路,与其既操作a和b,不如就只操作a,最大步数就是把a全部删除的步数,这时候再一次遍历,如果当前字符是a,则步数减一(因为在基准的左侧是不允许有b的,所以当前字符是a时,当前的a是不需要删除的,而最大步数里肯定是加了当前的a的,所以需要把最大步数减一),如果当前字符是b,则需要删除当前的b字符(因为每找到一个b,在下一步操作时,为了保证左侧没有b,需要将b删掉,这样就要多走一部,所以最大步数要加一)
以该字符串为例 : "aababbab"
第一次循环,max = 4;
第二次循环 (以下括号内为需要操作删除的字符)
i = 0, max = 4 - 1 =3 得到结果是 a(a)b(a)bb(a)b
i = 1, max = 3 -1 = 2 得到结果是 aab(a)bb(a)b
i = 2, max = 2 +1 = 3 得到结果是 aa(b)(a)bb(a)b
i = 3, max = 3 - 1 = 2 得到结果是 aa(b)abb(a)b
i = 4, max = 2 + 1 = 3 得到结果是 aa(b)a(b)b(a)b
i = 5, max = 3 + 1 = 4 得到结果是 aa(b)a(b)(b)(a)b
i = 6, max = 4 - 1 = 3 得到结果是 aa(b)a(b)(b)ab
i = 7, max = 3 + 1 = 4 得到结果是 aa(b)a(b)(b)a(b)
得出最小值是2
代码如下:
public int minimumDeletions2(String s) {
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == 'a') {
count ++;
}
}
int res = count;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == 'a') {
count --;
} else {
count ++;
}
if (res > count) {
res = count;
}
}
return res;
}