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

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

难度:

标签:

题目描述

代码结果

运行时间: 99 ms, 内存: 16.4 MB


/*
 * 思路:
 * 1. 使用Java Streams统计字符串a和b中每个字符的频率。
 * 2. 尝试将a中的每个字符变得严格小于b中的每个字符。
 * 3. 尝试将b中的每个字符变得严格小于a中的每个字符。
 * 4. 尝试将a和b中的每个字符变为相同的字符。
 * 5. 计算每种情况下的最小操作数,返回其中的最小值。
 */

import java.util.stream.IntStream;

public class Solution {
    public int minCharacters(String a, String b) {
        int[] countA = new int[26];
        int[] countB = new int[26];
        int lenA = a.length();
        int lenB = b.length();

        a.chars().forEach(c -> countA[c - 'a']++);
        b.chars().forEach(c -> countB[c - 'a']++);

        int res = Integer.MAX_VALUE;

        // Case 3: Change a and b to the same letter
        res = IntStream.range(0, 26)
                        .map(i -> lenA + lenB - countA[i] - countB[i])
                        .min()
                        .orElse(res);

        // Case 1 and Case 2
        for (int i = 0; i < 25; i++) {
            countA[i + 1] += countA[i];
            countB[i + 1] += countB[i];
            res = Math.min(res, lenA - countA[i] + countB[i]); // Case 1
            res = Math.min(res, lenB - countB[i] + countA[i]); // Case 2
        }

        return res;
    }
}

解释

方法:

题解采用了通过计数的方式来解决问题。首先,通过Counter统计字符串a和b中每个字符的出现次数。然后,遍历从字符'a'到'z'的每个字符,对于每个字符c,计算三种操作的成本:1) 将a中所有字符变为c,b中所有字符变为c;2) 将a中所有字符变得小于c,b中所有字符变得大于c;3) 将b中所有字符变得小于c,a中所有字符变得大于c。利用累积计数(prevA和prevB),可以方便地计算在当前字符c之前或之后,字符串需要变动的字符数。最后,选取三种操作中最小的操作数作为答案。

时间复杂度:

O(m+n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在计算最少操作数时,要初始化操作数为字符串a和b的长度之和?
初始化操作数为字符串a和b的长度之和(m + n)是因为这代表了将a和b中的每个字符都改变为另一个完全不同的字符的最极端情况。这样的初始化提供了一个上限,确保我们在后续计算中,考虑各种可能的字符变换操作时,能找到一个真实的、更小的最小操作数。
🦆
在计算将a中所有字符变得小于c,b中所有字符变得大于c的操作成本时,为什么使用m - prevA + prevB这种计算方式?
在此计算方式中,m - prevA 表示将a中所有大于等于字符c的字符变为小于c的字符所需的最少变动次数,因为prevA是a中小于等于c的字符的累积计数,所以m - prevA就是剩余需要变动的字符数。同理,prevB表示b中小于等于c的字符数,因此需要将这些字符变为大于c的字符,直接使用prevB即可。因此,总的操作次数为将a中的一部分字符减小,和将b中的一部分字符增大,即m - prevA + prevB。
🦆
在遍历字符时,为什么最后一个字符z的情况只考虑将a和b变为同一个字符,而不考虑a全小于b或b全小于a的情况?
因为字符z是字母表中的最后一个字符,不存在比z更大的字符。因此,在考虑将a中的字符全部变小于b或b中的字符全部变小于a的情况时,不可能实现a中的字符全小于z或b中的字符全小于z的条件。所以,对于字符z,只需要考虑将a和b中的所有字符都变为z的情况,这是唯一可行的操作。
🦆
题解中提到的累积计数prevA和prevB是如何帮助优化计算过程的?
累积计数prevA和prevB通过记录到当前字符为止,在a和b中小于等于当前字符的字符的总数,帮助快速计算不同变换操作所需的字符数。这种方法避免了对每个可能的字符变换重新遍历整个a或b字符串来计数,从而大大减少了计算的复杂度和执行时间。通过累积计数,我们可以直接利用已有的统计信息,快速得到任何字符c之前或之后的字符变动需求,从而实现高效的最优解搜索。

相关问题