22. 最少字符串操作次数 | 豆包 MarsCode 刷题

59 阅读1分钟

问题可以转化为:
给定 26 个非负整数,问最少进行多少次下列操作才能使这 26 个数全部变为 0011
操作:取一个不小于 22 的数,令其值减 22,随后再取一个数,令其值加 11

采取以下的贪心策略:

  1. 暂时延后“加 11”操作,先做“减 22”操作。减去尽可能多的 22。显然,这样做之后这 26 个数全部变为 0011
  2. 补上第 1 步中的“加 11”操作。我们希望,补上这些操作之后,使这些数再次减小到 0011 所需的操作次数尽可能少。因此,我们按如下顺序进行“加 11”操作,直到补足所有的“加 11”操作:
    (1) 遍历第 1 步之后变为 00 的数,使之加 11
    (2) 第 (1) 步后所有数都变为 11。反复遍历这 26 个数,每遍历到一个数都使之加 11
  3. 若 26 个数中还存在不小于 22 的数,跳回第 1 步。

时间复杂度:Θ(S)\Theta(|S|)
空间复杂度:O(1)O(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;
}