1. 题目来源
2. 题目解析
贪心问题,考试的时候用 erase()
函数进行实质上的删除,就一直超时,晚上做题的思路确实不够灵敏。
思路:
- 双指针找合法子串,贪心计算子串中最大的分数
- 假设
x > y
,若出现x <= y
的情况则交换x
和y
的值,并将所有的a
和b
进行交换,这也是处理该类问题的常见方式。 - 从后向前贪心计算合法子串的最大分数,用一个变量
c
来记录末尾有多少可使用的b
,其实对于这个b
来讲,它能组成'ab'
或'ba'
,当前假设x > y
,则肯定是组成'ab'
是最优的选择。 - 记录合法子串中的
a
和b
数量,能操作的最大次数是min(A, B)
,上面贪心操作了t
次,每次加x
分,故总分就是y * (min(A, B) - t) + x * t
- 时间复杂度: O ( n ) O(n) O(n)。
- 空间复杂度: O ( 1 ) O(1) O(1)
代码:
class Solution {
public:
int maximumGain(string s, int x, int y) {
if (x < y) {
swap(x, y);
for (auto &c : s)
if (c == 'a') c = 'b';
else if (c == 'b') c = 'a';
}
int res = 0;
for (int i = 0, j = 0; i < s.size(); i ++ ) {
if (s[i] != 'a' && s[i] != 'b') continue;
j = i + 1;
while (j < s.size() && (s[j] == 'a' || s[j] == 'b')) j ++ ;
int a = 0, b = 0, t = 0, c = 0;
for (int k = j - 1; k >= i; k -- ) {
if (s[k] == 'a') {
a ++ ;
if (c > 0) {
t ++ ;
c -- ;
}
} else {
b ++ ;
c ++ ;
}
}
res += x * t + (min(a, b) - t) * y;
i = j - 1;
}
return res;
}
};