问题可以转化为:
给定 26 个非负整数,问最少进行多少次下列操作才能使这 26 个数全部变为 或 。
操作:取一个不小于 的数,令其值减 ,随后再取一个数,令其值加 。
采取以下的贪心策略:
- 暂时延后“加 ”操作,先做“减 ”操作。减去尽可能多的 。显然,这样做之后这 26 个数全部变为 或 。
- 补上第 1 步中的“加 ”操作。我们希望,补上这些操作之后,使这些数再次减小到 或 所需的操作次数尽可能少。因此,我们按如下顺序进行“加 ”操作,直到补足所有的“加 ”操作:
(1) 遍历第 1 步之后变为 的数,使之加 。
(2) 第 (1) 步后所有数都变为 。反复遍历这 26 个数,每遍历到一个数都使之加 。 - 若 26 个数中还存在不小于 的数,跳回第 1 步。
时间复杂度:。
空间复杂度:。
代码(C++):
#include <string>
int solution(const std::string& S) {
int a[26] = {};
for (char c : S) {
++a[c - 'a'];
}
int ans = 0;
while (true) {
int cnt = 0;
for (int& x : a) {
cnt += x / 2;
x %= 2;
}
if (cnt == 0) {
break;
}
ans += cnt;
for (int& x : a) {
if (x == 0) {
x = 1;
if (--cnt == 0) {
break;
}
}
}
while (cnt > 0) {
for (int& x : a) {
++x;
if (--cnt == 0) {
break;
}
}
}
}
return ans;
}