根据题意,我们先统计 licensePlate 中每个字母的出现次数(忽略大小写),然后遍历 words 中的每个单词,若 26 个字母在该单词中的出现次数均不小于在 licensePlate 中的出现次数,则该单词是一个补全词。返回最短且最靠前的补全词。
[sol1-Python3]
1 2 3 4
classSolution: defshortestCompletingWord(self, licensePlate: str, words: List[str]) -> str: cnt = Counter(ch.lower() for ch in licensePlate if ch.isalpha()) returnmin((word for word in words ifnot cnt - Counter(word)), key=len)
funcshortestCompletingWord(licensePlate string, words []string) (ans string) { cnt := [26]int{} for _, ch := range licensePlate { if unicode.IsLetter(ch) { cnt[unicode.ToLower(ch)-'a']++ } }
next: for _, word := range words { c := [26]int{} for _, ch := range word { c[ch-'a']++ } for i := 0; i < 26; i++ { if c[i] < cnt[i] { continue next } } if ans == "" || len(word) < len(ans) { ans = word } } return }
char * shortestCompletingWord(char * licensePlate, char ** words, int wordsSize){ int cnt[26]; int n = strlen(licensePlate); memset(cnt, 0 ,sizeof(cnt));
for(int i = 0; i < n; ++i) { if (isalpha(licensePlate[i])) { ++cnt[tolower(licensePlate[i]) - 'a']; } } int idx = -1; int minLen = INT_MAX; for (int i = 0; i < wordsSize; ++i) { int currLen = strlen(words[i]); int c[26]; memset(c, 0, sizeof(c)); for (int j = 0; j < currLen; ++j) { ++c[words[i][j] - 'a']; } bool ok = true; for (int j = 0; j < 26; ++j) { if (c[j] < cnt[j]) { ok = false; break; } } if (ok && (idx < 0 || currLen < minLen)) { minLen = currLen; idx = i; } } return words[idx]; }
复杂度分析
时间复杂度:O(N+L+M\cdot |\Sigma|),其中 N 是字符串 licensePlate 的长度,L 是 words 中的所有字符串的长度之和,M 是 words 数组的长度,|\Sigma| 为字符集合的大小,本题中有 26 个英文字母,即 |\Sigma|=26。