删除字符使频率相同

标签: 哈希表 字符串 计数

难度: Easy

给你一个下标从 0 开始的字符串 word ,字符串只包含小写英文字母。你需要选择 一个 下标并 删除 下标处的字符,使得 word 中剩余每个字母出现 频率 相同。

如果删除一个字母后,word 中剩余所有字母的出现频率都相同,那么返回 true ,否则返回 false 。

注意:

  • 字母 x 的 频率 是这个字母在字符串中出现的次数。
  • 必须 恰好删除一个字母,不能一个字母都不删除。

示例 1:

输入:word = "abcc"
输出:true
解释:选择下标 3 并删除该字母:word 变成 "abc" 且每个字母出现频率都为 1 。

示例 2:

输入:word = "aazz"
输出:false
解释:我们必须删除一个字母,所以要么 "a" 的频率变为 1 且 "z" 的频率为 2 ,要么两个字母频率反过来。所以不可能让剩余所有字母出现频率相同。

提示:

  • 2 <= word.length <= 100
  • word 只包含小写英文字母。

Submission

运行时间: 26 ms

内存: 16.0 MB

class Solution:

    def equalFrequency(self, word: str) -> bool:
        f1, f2 = True, True
        c = Counter(word)
        lc = list(c.values())

        lc.sort()
        lc[0] -= 1
        if len(set(filter(lambda x: x > 0, lc))) != 1:
            f1 = False            
        
        lc[0] += 1
        lc[-1] -= 1

        if len(set((filter(lambda x: x > 0, lc)))) != 1:
            f2 = False

        return f1 or f2

Explain

这个题解的核心思路是尝试删除字符串中任一字符,然后检查剩余字符的频率是否一致。首先,利用Counter统计字符串中每个字符的出现频率,然后将这些频率排序。之后,算法尝试两种可能的删除方式:1)删除出现频率最少的字符后检查剩余字符的频率是否一致;2)删除出现频率最多的字符后检查剩余字符的频率是否一致。如果其中任一操作后所有字符的频率都相同,则返回true,否则返回false。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:

    def equalFrequency(self, word: str) -> bool:
        # 设置两个标志变量,分别对应两种删除策略的可能性
        f1, f2 = True, True
        # 计数器c来统计每个字符的频率
        c = Counter(word)
        # 将频率转换成列表并排序
        lc = list(c.values())
        lc.sort()
        # 尝试删除最小频率的字符
        lc[0] -= 1
        # 检查是否所有剩余的频率都相同
        if len(set(filter(lambda x: x > 0, lc))) != 1:
            f1 = False
        
        # 恢复初始状态,尝试删除最大频率的字符
        lc[0] += 1
        lc[-1] -= 1
        # 检查是否所有剩余的频率都相同
        if len(set((filter(lambda x: x > 0, lc)))) != 1:
            f2 = False

        # 如果任一策略成功,返回true
        return f1 or f2

Explore

这种策略基于一个观察,即影响字符频率统一性的往往是频率最高和最低的字符。删除频率最少的字符可能会将其频率降至0,从而可能帮助实现其它字符频率的一致性。同理,删除频率最高的字符可能会降低频率差异,使其他字符的频率更接近。这种方法是基于减少频率差异的最直接方式,而删除中间频率的字符通常不会直接影响频率的一致性,因此效率较低,不是首选策略。

不需要重新排序lc列表。因为仅仅是对列表中的一个元素进行增减,这不会改变列表中元素的相对顺序。即使是对最小或最大频率的元素进行修改,只要这些修改不导致元素之间的顺序关系改变(例如从大到小变为从小到大),原来的排序状态依然有效。

算法设计是为了检查删除一个字符后是否可以使所有剩余字符的频率完全相同。如果存在小的频率差异(例如一个字符的频率比其他字符多一个),则该算法还是会返回false,因为它严格要求所有的频率必须一致。对于这种情况,算法不会误判,但也不会提供容错处理,即不考虑接近但不完全相同的频率情况。

使用filter和set函数进行频率检查通常是安全的,因为filter函数用于移除频率中的零值(即完全删除的字符),而set用于检查频率的唯一性。潜在的问题可能出现在不正确处理元素频率为0的情况,或者误解set函数的功能,误以为它能处理除0以外的细微频率差异。只要正确实现,这种方法不会导致错误判断。