小U得到一个只包含小写字母的字符串 S。她可以执行如下操作:每次选择字符串中两个相同的字符删除,然后在字符串末尾添加一个任意的小写字母。小U想知道,最少需要多少次操作才能使得字符串中的所有字母都不相同? 测试样例
样例1: 输入:S = "abab" 输出:2
样例2: 输入:S = "aaaa" 输出:2
样例3: 输入:S = "abcabc" 输出:3
分析:
我们需要进行一系列操作,使得字符串中的所有字母都不重复。每次操作可以选择删除两个相同的字符,并在字符串的末尾添加一个新的字母。我们的目标是找到最少需要多少次操作才能达到这个目标。
思路分析
-
问题的核心: 我们需要尽量消除掉重复的字符。每次选择两个相同的字符进行删除,然后可以在末尾添加一个任意的小写字母。因此,关键问题是如何有效地删除重复字符,减少操作次数。
-
操作的步骤:
- 删除两个相同的字符: 每次删除两个相同的字符,并且替换成一个新的字符(通常是一个不会与当前字符串中的其他字符重复的小写字母)。
- 终止条件: 当字符串中所有字母都不再重复时,操作结束。
-
思考操作次数:
- 每次操作的核心是选择两个相同的字符并删除,且每次删除两个字符都能减少一个重复字符。因此,实际上,想要消除所有重复字符,我们需要找到所有字母出现次数大于1的字符。
- 对于每个字母,假设它出现了
c次,那么要将这些字母从字符串中完全去除,至少需要进行c // 2次操作(每次操作去除两个相同的字符)。如果c是奇数,那么剩下一个字符需要再进行一次操作。
-
思路简化:
- 计算频次: 首先统计每个字符在字符串中的出现频次。
- 操作次数: 对于每个字符,操作次数等于其出现次数
count // 2,剩余部分如果是奇数,还需要加一次操作。
-
最终操作次数: 所有字符的操作次数之和就是我们最少需要的操作次数。
解题步骤
- 统计每个字符的出现次数。
- 对于每个字符,计算
count // 2次操作,剩余字符如果有多余的,还需要额外一次操作。 - 输出操作次数的总和。
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或更小,直接返回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) 次操作即可。