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

46 阅读5分钟

小U得到一个只包含小写字母的字符串 S。她可以执行如下操作:每次选择字符串中两个相同的字符删除,然后在字符串末尾添加一个任意的小写字母。小U想知道,最少需要多少次操作才能使得字符串中的所有字母都不相同? 测试样例

样例1: 输入:S = "abab" 输出:2

样例2: 输入:S = "aaaa" 输出:2

样例3: 输入:S = "abcabc" 输出:3

分析:

我们需要进行一系列操作,使得字符串中的所有字母都不重复。每次操作可以选择删除两个相同的字符,并在字符串的末尾添加一个新的字母。我们的目标是找到最少需要多少次操作才能达到这个目标。

思路分析

  1. 问题的核心: 我们需要尽量消除掉重复的字符。每次选择两个相同的字符进行删除,然后可以在末尾添加一个任意的小写字母。因此,关键问题是如何有效地删除重复字符,减少操作次数。

  2. 操作的步骤:

    1. 删除两个相同的字符: 每次删除两个相同的字符,并且替换成一个新的字符(通常是一个不会与当前字符串中的其他字符重复的小写字母)。
    2. 终止条件: 当字符串中所有字母都不再重复时,操作结束。
  3. 思考操作次数:

    1. 每次操作的核心是选择两个相同的字符并删除,且每次删除两个字符都能减少一个重复字符。因此,实际上,想要消除所有重复字符,我们需要找到所有字母出现次数大于1的字符。
    2. 对于每个字母,假设它出现了 c 次,那么要将这些字母从字符串中完全去除,至少需要进行 c // 2 次操作(每次操作去除两个相同的字符)。如果 c 是奇数,那么剩下一个字符需要再进行一次操作。
  4. 思路简化:

    1. 计算频次: 首先统计每个字符在字符串中的出现频次。
    2. 操作次数: 对于每个字符,操作次数等于其出现次数 count // 2,剩余部分如果是奇数,还需要加一次操作。
  5. 最终操作次数: 所有字符的操作次数之和就是我们最少需要的操作次数。

解题步骤

  1. 统计每个字符的出现次数。
  2. 对于每个字符,计算 count // 2 次操作,剩余字符如果有多余的,还需要额外一次操作。
  3. 输出操作次数的总和。
from collections import Counter

def solution(S: str) -> int:
    # 统计每个字符的出现次数
    count = Counter(S)
    
    operations = 0
    # 遍历每个字符的出现次数
    for freq in count.values():
        # 对于每个字符,去除一对字符需要 freq // 2 次操作
        operations += freq // 2
        # 如果字符出现次数是奇数,剩余一个字符还需要一次操作
        if freq % 2 == 1:
            operations += 1
    
    return operations

但是存在错误

问题原因分析:

  1. 如果字符串只有一个字符,则它已经是唯一的,无需进行任何操作。代码需要额外处理这种边界条件。
  2. 当前代码可能默认对每个字符都进行了计算,而没有判断输入字符串是否已经满足条件。
  3. 在开始时检查字符串长度,如果长度为1或更小,直接返回0,因为此时字符串已经满足条件,无需操作。
from collections import Counter

def solution(S: str) -> int:
    # 如果字符串长度为1或小于1,直接返回0
    if len(S) <= 1:
        return 0
    
    # 统计每个字符的出现次数
    count = Counter(S)
    
    operations = 0
    # 遍历每个字符的出现次数
    for freq in count.values():
        # 对于每个字符,去除一对字符需要 freq // 2 次操作
        operations += freq // 2
        # 如果字符出现次数是奇数,剩余一个字符还需要一次操作
        if freq % 2 == 1:
            operations += 1
    
    return operations

当前逻辑中,计算字符出现次数时,每 freq // 2 次操作可以去掉两两匹配的字符,但剩余的字符没有被正确处理。

如果字符总数是偶数,比如 10 个 a,那么需要 (freq // 2) 次操作即可。但如果字符总数是奇数,比如 11 个 a,剩余 1 个字符时没有必要额外增加一次操作(因为最后剩下的字符是有效的,且不需要处理)。

修复逻辑时,我们需要考虑:每次操作是两两消除,因此总操作次数应该是 (总字符数 // 2),而非直接加多余的操作。

from collections import Counter

def solution(S: str) -> int:
    # 如果字符串长度为1或小于1,直接返回0
    if len(S) <= 1:
        return 0
    
    # 统计每个字符的出现次数
    count = Counter(S)
    
    operations = 0
    # 遍历每个字符的出现次数
    for freq in count.values():
        # 每两个相同字符需要一次操作,因此直接加上 freq // 2
        operations += freq // 2
    
    return operations

1.删除了多余的奇数逻辑。对于剩余的单个字符无需额外操作,因为它最终会保留在结果中。

2.每两两配对需要一个操作,因此直接累计 (freq // 2) 次操作即可。