【Leetcode】1737. 满足三条件之一需改变的最少字符数——1953

📝 题目

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

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

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

  • a 中的 每个字母 在字母表中 严格小于 b 中的 每个字母
  • b 中的 每个字母 在字母表中 严格小于 a 中的 每个字母
  • ab 同一个 字母组成。

返回达成目标所需的 最少 操作数。

提示:

  • 1 <= a.length, b.length &lt;= 105
  • ab 只由小写字母组成

🔍 思路

由于题目的目的是将两个字符串分割开来,一个字符串严格大于另外一个。

那么考虑一个分界点,如 一个字符串中所有字母都是小于等于'x',另外一个字符串里边所有字母都是严格大于'x'的(具体是'y'还是'z'到是无所谓)

上述分界点是小的字符串可以等于分界点,反之如果考虑小的严格小于分界点,大的可以等于分界点也是可以的,下列分析以前者小的可以等于分界点为准。

根据上述分析出的分界点,假定我们当前考虑的分界点是'x',那么如果计算当前分界点下的操作数?
具体的操作有两种:

  1. 一种是将a变为全为小于等于'x'的字符,b变为全大于'x'的字符。此时的操作数将a中大于'x'的数目+b中小于等于'x'的数目=len(a)-a中小于等于'x'的数目+b中小于等于'x'的数目
  2. 二是将b变为全为小于等于'x'的字符,a变为全大于'x'的字符。此时的操作数将b中大于'x'的数目+a中小于等于'x'的数目=len(b)-b中小于等于'x'的数目+a中小于等于'x'的数目

可以看到上述分析实际上一个前缀和。即小于等于'X'字符的数目


此外,我们也可以将a和b变为同一个字符,此时我们也可以借助这个分界点,将所有的字符都变为这个分界点。


因此在具体实现的过程中,我们先统计每个字符在a和b中的个数
之后计算前缀和,最后枚举分界点即可。

需要注意的是,由于字母'z'为最大的,因此这个分界点是不能为'z'的。

✍️ 代码实现

class Solution:
    def minCharacters(self, a: str, b: str) -> int:
        m, n = len(a), len(b)
        # 统计字符串中每个字符出现的次数
        ta = [0] * 26
        tb = [0] * 26
        # 由于a b 不一定长度相等,因此需要分别统计
        for x in a:
            ta[ord(x) - ord('a')] += 1
        for y in b:
            tb[ord(y) - ord('a')] += 1
        # 计算前缀和
        ca = list(accumulate(ta))
        cb = list(accumulate(tb))
        # 最后一个位置不能作为分界点,但是可以将所有的字符变为'z'
        ans = m + n-ta[-1]-tb[-1]
        for i in range(25):
            ans = min(ans, m - ca[i] + cb[i], n-cb[i]+ca[i],m+n-ta[i]-tb[i])
        return ans
posted @ 2024-12-27 17:17  TICSMC  阅读(15)  评论(0)    收藏  举报