52
52
53
53
<!-- 这里可写通用的实现逻辑 -->
54
54
55
+ ** 方法一:计数**
56
+
57
+ 我们先用哈希表或者一个长度为 $26$ 的数组 $cnt$ 统计字符串 ` licensePlate ` 中每个字母出现的次数,注意这里我们统一将字母转换为小写进行计数。
58
+
59
+ 然后,我们遍历数组 ` words ` 中的每个单词 $w$,如果单词 $w$ 的长度比答案 $ans$ 的长度长,那么我们直接跳过该单词。否则,我们再用哈希表或者一个长度为 $26$ 的数组 $t$ 统计单词 $w$ 中每个字母出现的次数。如果对于任意一个字母,$t$ 中该字母出现的次数小于 $cnt$ 中该字母出现的次数,那么我们也可以直接跳过该单词。否则,我们就找到了一个满足条件的单词,我们更新答案 $ans$ 为当前单词 $w$。
60
+
61
+ 时间复杂度 $O(n \times |\Sigma|)$,空间复杂度 $O(|\Sigma|)$,其中 $n$ 是数组 ` words ` 的长度,而 $\Sigma$ 是字符集,这里字符集为所有小写字母,因此 $|\Sigma| = 26$。
62
+
55
63
<!-- tabs:start -->
56
64
57
65
### ** Python3**
61
69
``` python
62
70
class Solution :
63
71
def shortestCompletingWord (self , licensePlate : str , words : List[str ]) -> str :
64
- def count (word ):
65
- counter = [0 ] * 26
66
- for c in word:
67
- counter[ord (c) - ord (' a' )] += 1
68
- return counter
69
-
70
- def check (counter1 , counter2 ):
71
- for i in range (26 ):
72
- if counter1[i] > counter2[i]:
73
- return False
74
- return True
75
-
76
- counter = count(c.lower() for c in licensePlate if c.isalpha())
77
- ans, n = None , 16
78
- for word in words:
79
- if n <= len (word):
72
+ cnt = Counter(c.lower() for c in licensePlate if c.isalpha())
73
+ ans = None
74
+ for w in words:
75
+ if ans and len (w) >= len (ans):
80
76
continue
81
- t = count(word)
82
- if check(counter, t):
83
- n = len (word)
84
- ans = word
77
+ t = Counter(w)
78
+ if all (v <= t[c] for c, v in cnt.items()):
79
+ ans = w
85
80
return ans
86
81
```
87
82
@@ -92,39 +87,34 @@ class Solution:
92
87
``` java
93
88
class Solution {
94
89
public String shortestCompletingWord (String licensePlate , String [] words ) {
95
- int [] counter = count(licensePlate. toLowerCase());
96
- String ans = null ;
97
- int n = 16 ;
98
- for (String word : words) {
99
- if (n <= word. length()) {
90
+ int [] cnt = new int [26 ];
91
+ for (int i = 0 ; i < licensePlate. length(); ++ i) {
92
+ char c = licensePlate. charAt(i);
93
+ if (Character . isLetter(c)) {
94
+ cnt[Character . toLowerCase(c) - ' a' ]++ ;
95
+ }
96
+ }
97
+ String ans = " " ;
98
+ for (String w : words) {
99
+ if (! ans. isEmpty() && w. length() >= ans. length()) {
100
100
continue ;
101
101
}
102
- int [] t = count(word);
103
- if (check(counter, t)) {
104
- n = word. length();
105
- ans = word;
102
+ int [] t = new int [26 ];
103
+ for (int i = 0 ; i < w. length(); ++ i) {
104
+ t[w. charAt(i) - ' a' ]++ ;
106
105
}
107
- }
108
- return ans;
109
- }
110
-
111
- private int [] count (String word ) {
112
- int [] counter = new int [26 ];
113
- for (char c : word. toCharArray()) {
114
- if (Character . isLetter(c)) {
115
- ++ counter[c - ' a' ];
106
+ boolean ok = true ;
107
+ for (int i = 0 ; i < 26 ; ++ i) {
108
+ if (t[i] < cnt[i]) {
109
+ ok = false ;
110
+ break ;
111
+ }
116
112
}
117
- }
118
- return counter;
119
- }
120
-
121
- private boolean check (int [] counter1 , int [] counter2 ) {
122
- for (int i = 0 ; i < 26 ; ++ i) {
123
- if (counter1[i] > counter2[i]) {
124
- return false ;
113
+ if (ok) {
114
+ ans = w;
125
115
}
126
116
}
127
- return true ;
117
+ return ans ;
128
118
}
129
119
}
130
120
```
@@ -135,74 +125,138 @@ class Solution {
135
125
class Solution {
136
126
public:
137
127
string shortestCompletingWord(string licensePlate, vector<string >& words) {
138
- vector<int > counter = count(licensePlate);
139
- int n = 16;
128
+ int cnt[ 26] {};
129
+ for (char& c : licensePlate) {
130
+ if (isalpha(c)) {
131
+ ++cnt[ tolower(c) - 'a'] ;
132
+ }
133
+ }
140
134
string ans;
141
- for (auto& word : words) {
142
- if (n <= word.size()) continue;
143
- vector<int > t = count(word);
144
- if (check(counter, t)) {
145
- n = word.size();
146
- ans = word;
135
+ for (auto& w : words) {
136
+ if (ans.size() && ans.size() <= w.size()) {
137
+ continue;
138
+ }
139
+ int t[ 26] {};
140
+ for (char& c : w) {
141
+ ++t[ c - 'a'] ;
142
+ }
143
+ bool ok = true;
144
+ for (int i = 0; i < 26; ++i) {
145
+ if (cnt[ i] > t[ i] ) {
146
+ ok = false;
147
+ break;
148
+ }
149
+ }
150
+ if (ok) {
151
+ ans = w;
147
152
}
148
153
}
149
154
return ans;
150
155
}
151
-
152
- vector<int> count(string& word) {
153
- vector<int> counter(26);
154
- for (char& c : word)
155
- if (isalpha(c))
156
- ++counter[tolower(c) - 'a'];
157
- return counter;
158
- }
159
-
160
- bool check (vector<int >& counter1, vector<int >& counter2) {
161
- for (int i = 0; i < 26; ++i)
162
- if (counter1[ i] > counter2[ i] )
163
- return false;
164
- return true;
165
- }
166
156
};
167
157
```
168
158
169
159
### **Go**
170
160
171
161
```go
172
- func shortestCompletingWord(licensePlate string, words []string) string {
173
- count := func(word string) []int {
174
- counter := make([]int, 26)
175
- for _, c := range word {
176
- if unicode.IsLetter(c) {
177
- counter[c-'a']++
178
- }
179
- }
180
- return counter
181
- }
182
-
183
- check := func(cnt1, cnt2 []int) bool {
184
- for i := 0; i < 26; i++ {
185
- if cnt1[i] > cnt2[i] {
186
- return false
187
- }
162
+ func shortestCompletingWord(licensePlate string, words []string) (ans string) {
163
+ cnt := [26]int{}
164
+ for _, c := range licensePlate {
165
+ if unicode.IsLetter(c) {
166
+ cnt[unicode.ToLower(c)-'a']++
188
167
}
189
- return true
190
168
}
191
-
192
- counter := count(strings.ToLower(licensePlate))
193
- var ans string
194
- n := 16
195
- for _, word := range words {
196
- if n <= len(word) {
169
+ for _, w := range words {
170
+ if len(ans) > 0 && len(ans) <= len(w) {
197
171
continue
198
172
}
199
- t := count(word)
200
- if check(counter, t) {
201
- n = len(word)
202
- ans = word
173
+ t := [26]int{}
174
+ for _, c := range w {
175
+ t[c-'a']++
176
+ }
177
+ ok := true
178
+ for i, v := range cnt {
179
+ if t[i] < v {
180
+ ok = false
181
+ break
182
+ }
183
+ }
184
+ if ok {
185
+ ans = w
203
186
}
204
187
}
205
- return ans
188
+ return
189
+ }
190
+ ```
191
+
192
+ ### ** TypeScript**
193
+
194
+ ``` ts
195
+ function shortestCompletingWord(licensePlate : string , words : string []): string {
196
+ const cnt: number [] = Array (26 ).fill (0 );
197
+ for (const c of licensePlate ) {
198
+ const i = c .toLowerCase ().charCodeAt (0 ) - 97 ;
199
+ if (0 <= i && i < 26 ) {
200
+ ++ cnt [i ];
201
+ }
202
+ }
203
+ let ans = ' ' ;
204
+ for (const w of words ) {
205
+ if (ans .length && ans .length <= w .length ) {
206
+ continue ;
207
+ }
208
+ const t = Array (26 ).fill (0 );
209
+ for (const c of w ) {
210
+ ++ t [c .charCodeAt (0 ) - 97 ];
211
+ }
212
+ let ok = true ;
213
+ for (let i = 0 ; i < 26 ; ++ i ) {
214
+ if (t [i ] < cnt [i ]) {
215
+ ok = false ;
216
+ break ;
217
+ }
218
+ }
219
+ if (ok ) {
220
+ ans = w ;
221
+ }
222
+ }
223
+ return ans ;
224
+ }
225
+ ```
226
+
227
+ ### ** Rust**
228
+
229
+ ``` rust
230
+ impl Solution {
231
+ pub fn shortest_completing_word (license_plate : String , words : Vec <String >) -> String {
232
+ let mut cnt = vec! [0 ; 26 ];
233
+ for c in license_plate . chars () {
234
+ if c . is_ascii_alphabetic () {
235
+ cnt [((c . to_ascii_lowercase () as u8 ) - b 'a' ) as usize ] += 1 ;
236
+ }
237
+ }
238
+ let mut ans = String :: new ();
239
+ for w in words {
240
+ if ! ans . is_empty () && w . len () >= ans . len () {
241
+ continue ;
242
+ }
243
+ let mut t = vec! [0 ; 26 ];
244
+ for c in w . chars () {
245
+ t [((c as u8 ) - b 'a' ) as usize ] += 1 ;
246
+ }
247
+ let mut ok = true ;
248
+ for i in 0 .. 26 {
249
+ if t [i ] < cnt [i ] {
250
+ ok = false ;
251
+ break ;
252
+ }
253
+ }
254
+ if ok {
255
+ ans = w ;
256
+ }
257
+ }
258
+ ans
259
+ }
206
260
}
207
261
```
208
262
0 commit comments