2024华为OD试题及答案-A070-递增字符串

题目描述

定义字符串完全由 ‘A’ 和 ‘B’组成,当然也可以全是’A’或全是’B’。如果字符串从前往后都是以字典序排列的,那么我们称之为严格递增字符串。
给出一个字符串s,允许修改字符串中的任意字符,即可以将任何的’A’修改成’B’,也可以将任何的’B’修改成’A’,
求可以使s满足严格递增的最小修改次数。

0 < s的长度 < 100000。

输入描述

输入一个字符串: “AABBA”

输出描述

输出:1

用例
输入AABBA
输出1
说明修改最后一位得到AABBB。

解题思路分析

这道题的目的是将一个由字符 'A' 和 'B' 组成的字符串转换为一个严格递增的字符串,即所有的 'A' 都应该出现在所有的 'B' 之前。我们可以通过计算需要修改的最小次数来实现这一转换。

步骤分析:

  1. 问题描述简化:

    • 对于一个字符串,如果在某一位置存在一个 'B',且在它之前存在一个 'A',这就会导致不是严格递增的情况。我们需要决定要么将这些 'A' 修改成 'B',要么将这些 'B' 修改成 'A'。
  2. 思路:

    • 我们可以从左到右遍历字符串,同时记录每个位置左侧的 'A' 的数量以及右侧的 'B' 的数量。然后对于每一个位置,计算将左侧所有 'A' 转换为 'B' 和右侧所有 'B' 转换为 'A' 的总成本,取其中最小的值作为结果。
  3. 步骤:

    • 从左到右遍历字符串,记录每个位置前面有多少个 'A'。
    • 从右到左遍历字符串,记录每个位置后面有多少个 'B'。
    • 对于每一个位置,计算将左侧的 'A' 改为 'B' 或将右侧的 'B' 改为 'A' 的代价,选择最小的代价。
  4. 优化:

    • 考虑时间复杂度为 O(n),因此适用于处理长度较长的字符串。

C++ 代码实现

 
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int minOperationsToStrictlyIncreasing(string s) {
    int n = s.length();
    vector<int> leftA(n, 0), rightB(n, 0);

    // 计算左侧的A的数量
    for (int i = 1; i < n; ++i) {
        leftA[i] = leftA[i - 1] + (s[i - 1] == 'A' ? 1 : 0);
    }

    // 计算右侧的B的数量
    for (int i = n - 2; i >= 0; --i) {
        rightB[i] = rightB[i + 1] + (s[i + 1] == 'B' ? 1 : 0);
    }

    int minOps = min(rightB[0], leftA[n-1]); // 只修改全B或全A的情况
    for (int i = 0; i < n; ++i) {
        minOps = min(minOps, leftA[i] + rightB[i]);
    }

    return minOps;
}

int main() {
    string s;
    cin >> s;
    cout << minOperationsToStrictlyIncreasing(s) << endl;
    return 0;
}

Python 代码实现

 
def min_operations_to_strictly_increasing(s):
    n = len(s)
    left_a = [0] * n
    right_b = [0] * n

    # 计算左侧的A的数量
    for i in range(1, n):
        left_a[i] = left_a[i - 1] + (1 if s[i - 1] == 'A' else 0)

    # 计算右侧的B的数量
    for i in range(n - 2, -1, -1):
        right_b[i] = right_b[i + 1] + (1 if s[i + 1] == 'B' else 0)

    min_ops = min(right_b[0], left_a[-1])  # 只修改全B或全A的情况
    for i in range(n):
        min_ops = min(min_ops, left_a[i] + right_b[i])

    return min_ops

if __name__ == "__main__":
    s = input()
    print(min_operations_to_strictly_increasing(s))

解题说明

  1. 左右计数:我们分别计算从左至右和从右至左的累计 'A' 和 'B' 的数量,从而能够在每个位置快速确定两侧的修改代价。

  2. 最小修改次数:对于每一个位置,我们都计算两侧的修改代价并选择最小值作为最终的答案。

  3. 时间复杂度:由于我们只需要两次遍历字符串,所以时间复杂度为 O(n),可以处理较长的字符串。

这个解法非常高效,能够在较大输入规模下迅速得出结果。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值