今日题目

https://leetcode.com/problems/word-subsets/

解题思路

暴力解法的时间复杂度为 $O(N^2\times (L+D))$,其中 $N$ 为单词数组的长度,$L$ 为每个单词的长度,$D$ 为字符集大小(即 26 个字母)。 然而由于 $N \le 10^4$,暴力解法会超时。 进一步观察可以发现,我们无需逐一比较 words2 中的所有单词,只需统计 words2 中每个字符出现次数的最大值即可。 例如,若字符 ‘a’ 在 $words2[1]$ 中出现 3 次、在 $words2[2]$ 中出现 2 次、在 $words2[3]$ 中出现 4 次,那么 $words1[i]$ 中 ‘a’ 至少需要出现 4 次,才能被计入答案。 因此,我们只需统计 words1 中每个单词各字符的出现次数,以及 words2 中每个字符出现次数的最大值,再逐一比较即可。

算法步骤

统计 words1 中每个单词各字符的出现次数,以及 words2 中每个字符出现次数的最大值,然后逐一比较判断是否满足条件。

复杂度分析

  • 时间复杂度:$O(N \times (L + D))$,其中 $N$ 为单词数组的长度,$L$ 为每个单词的长度,$D$ 为字符集大小(即 26 个字母)。

  • 空间复杂度:$O(N \times D)$。

代码

class Solution:
    def wordSubsets(self, words1: List[str], words2: List[str]) -> List[str]:
        wordcnt1, wordcnt2 = [], [0] * 26
        a = ord('a')
        for word in words1:
            cnt = [0] * 26
            for ch in word:
                x = ord(ch) - a
                cnt[x] += 1
            wordcnt1.append(cnt)
        
        for word in words2:
            cnt = [0] * 26
            for ch in word:
                x = ord(ch) - a
                cnt[x] += 1
            
            for j in range(26):
                wordcnt2[j] = max(wordcnt2[j], cnt[j])

        ans = []
        for i in range(len(words1)):
            flag = True
            for k in range(26):
                if wordcnt1[i][k] < wordcnt2[k]:
                    flag = False
                    break
            if flag:
                ans.append(words1[i])
        
        return ans