《LeetCode之每日一题》:119.满足三条件之一需改变的最少字符数

满足三条件之一需改变的最少字符数


题目链接: 满足三条件之一需改变的最少字符数

有关题目

给你两个字符串 a 和 b ,二者均由小写字母组成。
一步操作中,你可以将 a 或 b 中的 任一字符 改变为
 任一小写字母 。

操作的最终目标是满足下列三个条件 之一 :

a 中的 每个字母 在字母表中 严格小于 b 中的 每个字母 。
b 中的 每个字母 在字母表中 严格小于 a 中的 每个字母 。
a 和 b 都 由 同一个 字母组成。
返回达成目标所需的 最少 操作数。
示例 1:

输入:a = "aba", b = "caa"
输出:2
解释:满足每个条件的最佳方案分别是:
1) 将 b 变为 "ccc"2 次操作,满足 a 中的每个字母都小于 b 中的每个字母;
2) 将 a 变为 "bbb" 并将 b 变为 "aaa"3 次操作,满足 b 中的每个字母都小于 a 中的每个字母;
3) 将 a 变为 "aaa" 并将 b 变为 "aaa"2 次操作,满足 a 和 b 由同一个字母组成。
最佳的方案只需要 2 次操作(满足条件 1 或者条件 3)。
示例 2:

输入:a = "dabadd", b = "cda"
输出:3
解释:满足条件 1 的最佳方案是将 b 变为 "eee"
提示:

1 <= a.length, b.length <= 10^5
a 和 b 只由小写字母组成

题解

法一:模拟
参考GTAlgorithm

思路:
找出一个基准字母,分别讨论三种情况
class Solution {
public:
    int minCharacters(string a, string b) {
        int m = a.size(), n = b.size();
        vector<int> va(26, 0), vb(26, 0);
        for (char ch : a)  ++va[ch - 'a'];
        for (char ch : b)  ++vb[ch - 'a'];
        int res = m + n;

        //case 1 :a每个字母 在字母表中 严格小于b 每个字母
        int case1 = m + n;
        for (int i = 0; i < 25; ++i){
            int cur = 0;
            for (int j = i + 1; j < 26; ++j) cur += va[j];
            for (int j = 0; j <= i; ++j) cur += vb[j];
            case1 = min(case1, cur);
        }
        res = min(res, case1);

        //case 2:b每个字母 在字母表中 严格小于a 每个字母
        int case2 = res;
        for (int i = 0; i < 25; ++i){
            int cur = 0;
            for (int j = i + 1; j < 26; ++j) cur += vb[j];
            for (int j = 0; j <= i; ++j) cur += va[j];
            case2 = min(case2, cur);
        }
        res = min(case2, res);

        //case 3:a b都 由 同一个 字母组成
        int case3 = res;
        for (int i = 0; i < 26; ++i){
            int cur = 0;
            for (int j = 0; j < 26; ++j){
                if (i == j) continue;
                cur += va[j] + vb[j];
            }
            case3 = min(case3, cur);
        }
        res = min(case3, res);
        return res;
    }
};

时间复杂度:O(N)
空间复杂度:O(1)
法二:计数+前缀和、后缀和
参考真新镇的小智

以 a = "dabadd", b = "cda"为例,分别统计出现字母的对应字母的次数

在这里插入图片描述

class Solution {
public:
    int minCharacters(string a, string b) {
        int m = a.size(), n = b.size();
        vector<int> va(26, 0), vb(26, 0);
        for (char ch : a) ++va[ch - 'a'];
        for (char ch : b) ++vb[ch - 'a'];
        
        int ans = INT_MAX, asum = 0, bsum = 0;
        for (int i = 0; i < 25; ++i){
            asum += va[i];
            bsum += vb[i];
            ans = min(min(ans, m - va[i] + n - vb[i]), min(m - asum + bsum, n - bsum + asum));
        }

        //统计都由同一个'z'组成所需的步数
        ans = min(ans, m - va[25] + n - vb[25]);
        return ans;
    }
};

时间复杂度:O(N)
空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值