77
77
78
78
<!-- solution:start -->
79
79
80
- ### 方法一
80
+ ### 方法一:模拟
81
+
82
+ 我们首先将句子按空格分割成单词,然后对每个单词进行检查,判断是否为有效单词。
83
+
84
+ 对于每个单词,我们可以使用一个布尔变量 $\textit{st}$ 来记录是否已经出现过连字符,然后遍历单词中的每个字符,根据题目描述的规则进行判断。
85
+
86
+ 对于每个字符 $s[ i] $,我们有以下几种情况:
87
+
88
+ - 如果 $s[ i] $ 是数字,那么 $s$ 不是有效单词,直接返回 $\text{false}$;
89
+ - 如果 $s[ i] $ 是标点符号('!'、'.'、',')且 $i < \text{len}(s) - 1$,那么 $s$ 不是有效单词,直接返回 $\text{false}$;
90
+ - 如果 $s[ i] $ 是连字符,那么我们需要判断是否满足以下条件:
91
+ - 连字符只能出现一次;
92
+ - 连字符不能出现在单词的开头或结尾;
93
+ - 连字符两侧必须是字母;
94
+ - 如果 $s[ i] $ 是字母,那么我们不需要做任何处理。
95
+
96
+ 最后,我们统计出句子中的有效单词数即可。
97
+
98
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是句子的长度。
81
99
82
100
<!-- tabs:start -->
83
101
@@ -86,24 +104,23 @@ tags:
86
104
``` python
87
105
class Solution :
88
106
def countValidWords (self , sentence : str ) -> int :
89
- def check (token ) :
90
- hyphen = False
91
- for i, c in enumerate (token ):
92
- if c.isdigit() or (c in ' !.,' and i < len (token ) - 1 ):
107
+ def check (s : str ) -> bool :
108
+ st = False
109
+ for i, c in enumerate (s ):
110
+ if c.isdigit() or (c in " !.," and i < len (s ) - 1 ):
93
111
return False
94
- if c == ' - ' :
112
+ if c == " - " :
95
113
if (
96
- hyphen
97
- or i == 0
98
- or i == len (token) - 1
99
- or not token[i - 1 ].islower()
100
- or not token[i + 1 ].islower()
114
+ st
115
+ or i in (0 , len (s) - 1 )
116
+ or not s[i - 1 ].isalpha()
117
+ or not s[i + 1 ].isalpha()
101
118
):
102
119
return False
103
- hyphen = True
120
+ st = True
104
121
return True
105
122
106
- return sum (check(token ) for token in sentence.split())
123
+ return sum (check(s ) for s in sentence.split())
107
124
```
108
125
109
126
#### Java
@@ -112,76 +129,142 @@ class Solution:
112
129
class Solution {
113
130
public int countValidWords (String sentence ) {
114
131
int ans = 0 ;
115
- for (String token : sentence. split(" " )) {
116
- if (check(token)) {
117
- ++ ans;
118
- }
132
+ for (String s : sentence. split(" " )) {
133
+ ans += check(s. toCharArray());
119
134
}
120
135
return ans;
121
136
}
122
137
123
- private boolean check (String token ) {
124
- int n = token. length();
125
- if (n == 0 ) {
126
- return false ;
138
+ private int check (char [] s ) {
139
+ if (s. length == 0 ) {
140
+ return 0 ;
127
141
}
128
- boolean hyphen = false ;
129
- for (int i = 0 ; i < n; ++ i) {
130
- char c = token. charAt(i);
131
- if (Character . isDigit(c) || (i < n - 1 && (c == ' !' || c == ' .' || c == ' ,' ))) {
132
- return false ;
142
+ boolean st = false ;
143
+ for (int i = 0 ; i < s. length; ++ i) {
144
+ if (Character . isDigit(s[i])) {
145
+ return 0 ;
146
+ }
147
+ if ((s[i] == ' !' || s[i] == ' .' || s[i] == ' ,' ) && i < s. length - 1 ) {
148
+ return 0 ;
133
149
}
134
- if (c == ' -' ) {
135
- if (hyphen || i == 0 || i == n - 1 || ! Character . isLetter(token. charAt(i - 1 ))
136
- || ! Character . isLetter(token. charAt(i + 1 ))) {
137
- return false ;
150
+ if (s[i] == ' -' ) {
151
+ if (st || i == 0 || i == s. length - 1 ) {
152
+ return 0 ;
138
153
}
139
- hyphen = true ;
154
+ if (! Character . isAlphabetic(s[i - 1 ]) || ! Character . isAlphabetic(s[i + 1 ])) {
155
+ return 0 ;
156
+ }
157
+ st = true ;
140
158
}
141
159
}
142
- return true ;
160
+ return 1 ;
143
161
}
144
162
}
145
163
```
146
164
147
- #### TypeScript
165
+ #### C++
148
166
149
- ``` ts
150
- function countValidWords(sentence : string ): number {
151
- let words = sentence .trim ().split (/ \s + / );
152
- let ans = 0 ;
153
- for (let word of words ) {
154
- if (isValied (word )) {
155
- ans ++ ;
167
+ ``` cpp
168
+ class Solution {
169
+ public:
170
+ int countValidWords(string sentence) {
171
+ auto check = [ ] (const string& s) -> int {
172
+ bool st = false;
173
+ for (int i = 0; i < s.length(); ++i) {
174
+ if (isdigit(s[ i] )) {
175
+ return 0;
176
+ }
177
+ if ((s[ i] == '!' || s[ i] == '.' || s[ i] == ',') && i < s.length() - 1) {
178
+ return 0;
179
+ }
180
+ if (s[ i] == '-') {
181
+ if (st || i == 0 || i == s.length() - 1) {
182
+ return 0;
183
+ }
184
+ if (!isalpha(s[ i - 1] ) || !isalpha(s[ i + 1] )) {
185
+ return 0;
186
+ }
187
+ st = true;
188
+ }
189
+ }
190
+ return 1;
191
+ };
192
+
193
+ int ans = 0;
194
+ stringstream ss(sentence);
195
+ string s;
196
+ while (ss >> s) {
197
+ ans += check(s);
156
198
}
199
+ return ans;
157
200
}
158
- return ans ;
201
+ };
202
+ ```
203
+
204
+ #### Go
205
+
206
+ ``` go
207
+ func countValidWords (sentence string ) (ans int ) {
208
+ check := func (s string ) int {
209
+ if len (s) == 0 {
210
+ return 0
211
+ }
212
+ st := false
213
+ for i , r := range s {
214
+ if unicode.IsDigit (r) {
215
+ return 0
216
+ }
217
+ if (r == ' !' || r == ' .' || r == ' ,' ) && i < len (s)-1 {
218
+ return 0
219
+ }
220
+ if r == ' -' {
221
+ if st || i == 0 || i == len (s)-1 {
222
+ return 0
223
+ }
224
+ if !unicode.IsLetter (rune (s[i-1 ])) || !unicode.IsLetter (rune (s[i+1 ])) {
225
+ return 0
226
+ }
227
+ st = true
228
+ }
229
+ }
230
+ return 1
231
+ }
232
+ for _ , s := range strings.Fields (sentence) {
233
+ ans += check (s)
234
+ }
235
+ return ans
159
236
}
237
+ ```
238
+
239
+ #### TypeScript
160
240
161
- function isValied(str : string ): boolean {
162
- let n = str .length ;
163
- let hasLine = false ;
164
- for (let i = 0 ; i < n ; i ++ ) {
165
- const char = str .charAt (i );
166
- if (/ ^ [0-9 ] $ / .test (char )) {
167
- return false ;
241
+ ``` ts
242
+ function countValidWords(sentence : string ): number {
243
+ const check = (s : string ): number => {
244
+ if (s .length === 0 ) {
245
+ return 0 ;
168
246
}
169
- if ( char == ' - ' ) {
170
- if ( hasLine ) return false ;
171
- else {
172
- hasLine = true ;
247
+ let st = false ;
248
+ for ( let i = 0 ; i < s . length ; ++ i ) {
249
+ if ( / \d / . test ( s [ i ])) {
250
+ return 0 ;
173
251
}
174
- let pre = str .charAt (i - 1 ),
175
- post = str .charAt (i + 1 );
176
- if (! / ^ [a-z ] $ / g .test (pre ) || ! / ^ [a-z ] $ / g .test (post )) {
177
- return false ;
252
+ if ([' !' , ' .' , ' ,' ].includes (s [i ]) && i < s .length - 1 ) {
253
+ return 0 ;
254
+ }
255
+ if (s [i ] === ' -' ) {
256
+ if (st || [0 , s .length - 1 ].includes (i )) {
257
+ return 0 ;
258
+ }
259
+ if (! / [a-zA-Z ] / .test (s [i - 1 ]) || ! / [a-zA-Z ] / .test (s [i + 1 ])) {
260
+ return 0 ;
261
+ }
262
+ st = true ;
178
263
}
179
264
}
180
- if (/ ^ [\!\.\, \s ] $ / .test (char ) && i != n - 1 ) {
181
- return false ;
182
- }
183
- }
184
- return true ;
265
+ return 1 ;
266
+ };
267
+ return sentence .split (/ \s + / ).reduce ((acc , s ) => acc + check (s ), 0 );
185
268
}
186
269
```
187
270
0 commit comments