可以输入的最大单词数

标签: 哈希表 字符串

难度: Easy

键盘出现了一些故障,有些字母键无法正常工作。而键盘上所有其他键都能够正常工作。

给你一个由若干单词组成的字符串 text ,单词间由单个空格组成(不含前导和尾随空格);另有一个字符串 brokenLetters ,由所有已损坏的不同字母键组成,返回你可以使用此键盘完全输入的 text 中单词的数目。

 

示例 1:

输入:text = "hello world", brokenLetters = "ad"
输出:1
解释:无法输入 "world" ,因为字母键 'd' 已损坏。

示例 2:

输入:text = "leet code", brokenLetters = "lt"
输出:1
解释:无法输入 "leet" ,因为字母键 'l' 和 't' 已损坏。

示例 3:

输入:text = "leet code", brokenLetters = "e"
输出:0
解释:无法输入任何单词,因为字母键 'e' 已损坏。

 

提示:

  • 1 <= text.length <= 104
  • 0 <= brokenLetters.length <= 26
  • text 由若干用单个空格分隔的单词组成,且不含任何前导和尾随空格
  • 每个单词仅由小写英文字母组成
  • brokenLetters互不相同 的小写英文字母组成

Submission

运行时间: 24 ms

内存: 16.1 MB

class Solution:
    def canBeTypedWords(self, text: str, brokenLetters: str) -> int:
        words = list(map(str, text.split()))
        ans = len(words)
        for word in words:
            for broken in brokenLetters:
                if broken in word:
                    ans -= 1
                    break
        return ans

Explain

该题解首先通过分割输入的字符串text来获取单词列表words。对于words中的每个单词,检查它是否包含brokenLetters中的任何字母。如果一个单词包含任何损坏的字母,则将能够成功输入的单词数量减一。这种方法逐个检验每个单词中是否包含损坏的字母,并在找到第一个损坏字母时停止检查该单词,以优化性能。

时间复杂度: O(n * b)

空间复杂度: O(n)

# 定义Solution类

class Solution:
    def canBeTypedWords(self, text: str, brokenLetters: str) -> int:
        # 将文本分割成单词列表
        words = list(map(str, text.split()))
        # 初始化可以输入的单词计数
        ans = len(words)
        # 遍历每个单词
        for word in words:
            # 检查每个损坏的字母是否在当前单词中
            for broken in brokenLetters:
                if broken in word:
                    # 如果找到损坏字母,减少计数并停止检查这个单词
                    ans -= 1
                    break
        # 返回可以完全输入的单词数
        return ans

Explore

当检查单词中是否包含损坏字母时,一旦发现第一个损坏字母,就意味着这个单词不能完全输入,因此继续检查其他字母是多余的。这种方法可以减少不必要的检查次数,提高算法的效率。例如,如果单词很长且损坏字母出现在单词开始部分,则早停可以显著减少比较操作,节省计算资源。

使用集合(Set)来存储损坏字母可以提高查找效率。集合的平均时间复杂度为O(1)来检查元素是否存在,相比于字符串的O(n)复杂度,使用集合可以更快地判断单词是否包含任何损坏字母。因此,将brokenLetters转化为一个集合,并对每个单词进行检查,可以提高整体算法的效率。

在这个特定的例子中,使用`map(str, text.split())`并没有特别的优势,因为`text.split()`本身就返回一个字符串列表。这里使用`map`可能是出于习惯或者为了在某些情况下确保每个元素都是字符串类型,但在处理普通的文本数据时,直接使用`text.split()`即可达到同样的效果,且更为直接和清晰。

当brokenLetters为空字符串时,确实进行了不必要的检查,因为没有字母需要被检查是否损坏。为了优化这种情况,可以在算法开始时检查`brokenLetters`是否为空。如果是空字符串,直接返回`len(words)`,因为没有任何字母是损坏的,所有单词都可以完整输入。这样可以避免在没有必要时遍历所有单词,提高算法的效率。