给你一个字符串 s ,它仅包含字符 'a' 和 'b' 。
你可以删除 s 中任意数目的字符,使得 s 平衡 。当不存在下标对 (i,j) 满足 i < j ,且 s[i] = 'b' 的同时 s[j] = 'a' ,此时认为 s 是平衡的。
请你返回使 s 平衡的最少删除次数。
示例 1:
输入:s = "aababbab"
输出:2
解释:你可以选择以下任意一种方案:
下标从 0 开始,删除第 2 和第 6 个字符("aababbab" -> "aaabbb"),
下标从 0 开始,删除第 3 和第 6 个字符("aababbab" -> "aabbbb")。
示例 2:
输入:s = "bbaaaaabb"
输出:2
解释:唯一的最优解是删除最前面两个字符。
提示:
- 1 <= s.length <= 105
- s[i] 要么是 'a' 要么是 'b'
方案一:对于每一个字符,都有两种情况,删或者不删。枚举出每一种情况,取删除次数最少的。时间复杂度为 O(2n), 这种方案会超时
int helper(string &s, string &b, int i, int count) {
if (i >= s.size())
return 0x7fffffff;
if (s == b) {
return count;
}
string s1 = s;
s1.erase(i, 1);
string b1 = b;
if (s[i] == 'a') {
b1.erase(b1.begin());
} else {
b1.erase(b1.end() - 1);
}
return min(helper(s, b, i + 1, count), helper(s1, b1, i, count + 1));
}
int minimumDeletions(string s) {
string balance = s;
sort(balance.begin(), balance.end());
return helper(s, balance, 0, 0);
}
方案二:假设有一条间隔,删除间隔左边的所有 'b', 删除间隔右边的所有 'a',此时的字符串是平衡的。间隔一开始在字符串的最左边,一直遍历到最右边,取修改最少的结果。
int minimumDeletions(string s) {
int leftB = 0, rightA = 0;
for (auto ch : s) {
if (ch == 'a')
++rightA;
}
int res = rightA;
for (auto ch : s) {
if (ch == 'a') {
--rightA;
} else {
++leftB;
}
res = min(res, leftB + rightA);
}
return res;
}