招式拆解 II

标签: 队列 哈希表 字符串 计数

难度: Easy

某套连招动作记作仅由小写字母组成的序列 arr,其中 arr[i]i 个招式的名字。请返回第一个只出现一次的招式名称,如不存在请返回空格。

示例 1:

输入:arr = "abbccdeff"
输出:'a'

示例 2:

输入:arr = "ccdd"
输出:' '

限制:

0 <= arr.length <= 50000

Submission

运行时间: 168 ms

内存: 15.1 MB

from collections import defaultdict


class Solution:
    def firstUniqChar(self, s: str) -> str:
        d = defaultdict(int)
        for char in s:
            d[char] += 1
        for char in s:
            if d[char] == 1:
                return char
        return " "

Explain

这个题解首先使用一个哈希表(通过defaultdict实现)来记录字符串中每个字符的出现次数。遍历一次字符串,对于每个字符,都在哈希表中增加其计数。之后再次遍历字符串,检查每个字符在哈希表中的计数值。第一个计数值为1的字符即为第一个只出现一次的字符。如果所有字符都被遍历完仍未找到,则返回一个空格字符。

时间复杂度: O(n)

空间复杂度: O(n)

from collections import defaultdict


class Solution:
    def firstUniqChar(self, s: str) -> str:
        # 创建一个defaultdict来记录每个字符的出现次数
        d = defaultdict(int)
        # 遍历字符串,增加每个字符的计数
        for char in s:
            d[char] += 1
        # 再次遍历字符串,寻找第一个计数为1的字符
        for char in s:
            if d[char] == 1:
                return char
        # 如果没有找到计数为1的字符,返回空格
        return ' '

Explore

使用`defaultdict`的主要优点是它自动为新加入字典的键提供一个默认值。在这个场景中,每当一个字符首次被遍历到时,`defaultdict`会自动将其计数初始化为0,然后立即增加计数,这样可以避免在字典中手动检查和设置默认值的步骤。这样的处理简化了代码并提高了效率。

在第一次遍历字符串时,已经为每个字符准确计算了总的出现次数,并存储在哈希表中。因此,当第二次遍历字符串时,我们可以直接访问每个字符的计数值。第一个遇到的计数值为1的字符,根据之前的统计,确实在整个字符串中只出现了一次。这种方法依赖于第一次遍历时已经完成的准确计数。

是的,此算法在处理空字符串时的返回值是正确的。当输入字符串长度为0时,由于没有字符进行遍历,第二次遍历也不会执行任何操作。因此,最终返回的是预设的空格字符 ' ',这符合题目要求处理找不到只出现一次的字符时的情况。

在处理所有相同字符的字符串时,此算法的效率仍然是线性的。第一次遍历将计算单个字符的出现次数,而第二次遍历则会检查相同的字符,确认它们的计数值都超过1。尽管结果是负面的(即所有字符出现次数都不是1),但算法的总体时间复杂度仍然是O(n),其中n是字符串的长度。