56
56
57
57
<!-- 这里可写通用的实现逻辑 -->
58
58
59
+ ** 方法一:枚举 + 哈希表**
60
+
61
+ 我们可以直接枚举所有子串的起点位置 $i$,找到以该位置所在的字符为首字符的所有子串,用哈希表 $s$ 记录子串的所有字符。
62
+
63
+ 如果子串中存在一个字母找不到对应的大写字母或者小写字母,那么不满足条件,否则取最长的且最早出现的子串。
64
+
65
+ 时间复杂度 $O(n^2 \times C)$,空间复杂度 $O(C)$。其中 $n$ 为字符串 $s$ 的长度,而 $C$ 为字符集的大小。
66
+
67
+ ** 方法二:枚举 + 位运算**
68
+
69
+ 与方法一类似,我们可以直接枚举所有子串的起点位置 $i$,找到以该位置所在的字符为首字符的所有子串,用两个整数 $lower$ 和 $upper$ 分别记录子串中小写字母和大写字母的出现情况。
70
+
71
+ 判断子串是否满足条件,只需要判断 $lower$ 和 $upper$ 中对应的位是否都为 $1$ 即可。
72
+
73
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(1)$。其中 $n$ 为字符串 $s$ 的长度。
74
+
59
75
<!-- tabs:start -->
60
76
61
77
### ** Python3**
62
78
63
79
<!-- 这里可写当前语言的特殊实现逻辑 -->
64
80
81
+ ``` python
82
+ class Solution :
83
+ def longestNiceSubstring (self , s : str ) -> str :
84
+ n = len (s)
85
+ ans = ' '
86
+ for i in range (n):
87
+ ss = set ()
88
+ for j in range (i, n):
89
+ ss.add(s[j])
90
+ if all (c.lower() in ss and c.upper() in ss for c in ss) and len (ans) < j - i + 1 :
91
+ ans = s[i: j + 1 ]
92
+ return ans
93
+ ```
94
+
65
95
``` python
66
96
class Solution :
67
97
def longestNiceSubstring (self , s : str ) -> str :
@@ -74,8 +104,8 @@ class Solution:
74
104
lower |= 1 << (ord (s[j]) - ord (' a' ))
75
105
else :
76
106
upper |= 1 << (ord (s[j]) - ord (' A' ))
77
- if lower == upper and j - i + 1 > len (ans) :
78
- ans = s[i : j + 1 ]
107
+ if lower == upper and len (ans) < j - i + 1 :
108
+ ans = s[i: j + 1 ]
79
109
return ans
80
110
```
81
111
@@ -85,10 +115,39 @@ class Solution:
85
115
86
116
``` java
87
117
class Solution {
118
+ public String longestNiceSubstring (String s ) {
119
+ int n = s. length();
120
+ int k = - 1 ;
121
+ int mx = 0 ;
122
+ for (int i = 0 ; i < n; ++ i) {
123
+ Set<Character > ss = new HashSet<> ();
124
+ for (int j = i; j < n; ++ j) {
125
+ ss. add(s. charAt(j));
126
+ boolean ok = true ;
127
+ for (char a : ss) {
128
+ char b = (char ) (a ^ 32 );
129
+ if (! (ss. contains(a) && ss. contains(b))) {
130
+ ok = false ;
131
+ break ;
132
+ }
133
+ }
134
+ if (ok && mx < j - i + 1 ) {
135
+ mx = j - i + 1 ;
136
+ k = i;
137
+ }
138
+ }
139
+ }
140
+ return k == - 1 ? " " : s. substring(k, k + mx);
141
+ }
142
+ }
143
+ ```
88
144
145
+ ``` java
146
+ class Solution {
89
147
public String longestNiceSubstring (String s ) {
90
148
int n = s. length();
91
- String ans = " " ;
149
+ int k = - 1 ;
150
+ int mx = 0 ;
92
151
for (int i = 0 ; i < n; ++ i) {
93
152
int lower = 0 , upper = 0 ;
94
153
for (int j = i; j < n; ++ j) {
@@ -98,82 +157,149 @@ class Solution {
98
157
} else {
99
158
upper |= 1 << (c - ' A' );
100
159
}
101
- if (lower == upper && j - i + 1 > ans. length()) {
102
- ans = s. substring(i, j + 1 );
160
+ if (lower == upper && mx < j - i + 1 ) {
161
+ mx = j - i + 1 ;
162
+ k = i;
103
163
}
104
164
}
105
165
}
106
- return ans ;
166
+ return k == - 1 ? " " : s . substring(k, k + mx) ;
107
167
}
108
168
}
109
169
```
110
170
111
- ### ** TypeScript **
171
+ ### ** C++ **
112
172
113
- ``` ts
114
- function longestNiceSubstring(s : string ): string {
115
- const n = s .length ;
116
- let ans = ' ' ;
117
- for (let i = 0 ; i < n ; i ++ ) {
118
- let lower = 0 ,
119
- upper = 0 ;
120
- for (let j = i ; j < n ; j ++ ) {
121
- const c = s .charCodeAt (j );
122
- if (c > 96 ) {
123
- lower |= 1 << (c - 97 );
124
- } else {
125
- upper |= 1 << (c - 65 );
126
- }
127
- if (lower == upper && j - i + 1 > ans .length ) {
128
- ans = s .substring (i , j + 1 );
173
+ ``` cpp
174
+ class Solution {
175
+ public:
176
+ string longestNiceSubstring(string s) {
177
+ int n = s.size();
178
+ int k = -1, mx = 0;
179
+ for (int i = 0; i < n; ++i) {
180
+ unordered_set<char > ss;
181
+ for (int j = i; j < n; ++j) {
182
+ ss.insert(s[ j] );
183
+ bool ok = true;
184
+ for (auto& a : ss) {
185
+ char b = a ^ 32;
186
+ if (!(ss.count(a) && ss.count(b))) {
187
+ ok = false;
188
+ break;
189
+ }
190
+ }
191
+ if (ok && mx < j - i + 1) {
192
+ mx = j - i + 1;
193
+ k = i;
194
+ }
129
195
}
130
196
}
197
+ return k == -1 ? "" : s.substr(k, mx);
131
198
}
132
- return ans ;
133
- }
199
+ };
134
200
```
135
201
136
- ### ** C++**
137
-
138
202
```cpp
139
203
class Solution {
140
204
public:
141
205
string longestNiceSubstring(string s) {
142
206
int n = s.size();
143
- string ans = "" ;
207
+ int k = -1, mx = 0 ;
144
208
for (int i = 0; i < n; ++i) {
145
209
int lower = 0, upper = 0;
146
210
for (int j = i; j < n; ++j) {
147
- if (islower(s[ j] ))
148
- lower |= 1 << (s[ j] - 'a');
149
- else
150
- upper |= 1 << (s[ j] - 'A');
151
- if (lower == upper && j - i + 1 > ans.size()) ans = s.substr(i, j - i + 1);
211
+ char c = s[j];
212
+ if (islower(c)) lower |= 1 << (c - 'a');
213
+ else upper |= 1 << (c - 'A');
214
+ if (lower == upper && mx < j - i + 1) {
215
+ mx = j - i + 1;
216
+ k = i;
217
+ }
152
218
}
153
219
}
154
- return ans ;
220
+ return k == -1 ? "" : s.substr(k, mx) ;
155
221
}
156
222
};
157
223
```
158
224
159
225
### ** Go**
160
226
161
227
``` go
162
- func longestNiceSubstring(s string) (ans string) {
163
- for i := range s {
164
- lower, upper := 0, 0
165
- for j := i; j < len(s); j++ {
228
+ func longestNiceSubstring (s string ) string {
229
+ n := len (s)
230
+ k , mx := -1 , 0
231
+ for i := 0 ; i < n; i++ {
232
+ ss := map [byte ]bool {}
233
+ for j := i; j < n; j++ {
234
+ ss[s[j]] = true
235
+ ok := true
236
+ for a := range ss {
237
+ b := a ^ 32
238
+ if !(ss[a] && ss[b]) {
239
+ ok = false
240
+ break
241
+ }
242
+ }
243
+ if ok && mx < j-i+1 {
244
+ mx = j - i + 1
245
+ k = i
246
+ }
247
+ }
248
+ }
249
+ if k < 0 {
250
+ return " "
251
+ }
252
+ return s[k : k+mx]
253
+ }
254
+ ```
255
+
256
+ ``` go
257
+ func longestNiceSubstring (s string ) string {
258
+ n := len (s)
259
+ k , mx := -1 , 0
260
+ for i := 0 ; i < n; i++ {
261
+ var lower , upper int
262
+ for j := i; j < n; j++ {
166
263
if unicode.IsLower (rune (s[j])) {
167
264
lower |= 1 << (s[j] - ' a' )
168
265
} else {
169
266
upper |= 1 << (s[j] - ' A' )
170
267
}
171
- if lower == upper && j-i+1 > len(ans) {
172
- ans = s[i : j+1]
268
+ if lower == upper && mx < j-i+1 {
269
+ mx = j - i + 1
270
+ k = i
173
271
}
174
272
}
175
273
}
176
- return
274
+ if k < 0 {
275
+ return " "
276
+ }
277
+ return s[k : k+mx]
278
+ }
279
+ ```
280
+
281
+ ### ** TypeScript**
282
+
283
+ ``` ts
284
+ function longestNiceSubstring(s : string ): string {
285
+ const n = s .length ;
286
+ let ans = ' ' ;
287
+ for (let i = 0 ; i < n ; i ++ ) {
288
+ let lower = 0 ,
289
+ upper = 0 ;
290
+ for (let j = i ; j < n ; j ++ ) {
291
+ const c = s .charCodeAt (j );
292
+ if (c > 96 ) {
293
+ lower |= 1 << (c - 97 );
294
+ } else {
295
+ upper |= 1 << (c - 65 );
296
+ }
297
+ if (lower == upper && j - i + 1 > ans .length ) {
298
+ ans = s .substring (i , j + 1 );
299
+ }
300
+ }
301
+ }
302
+ return ans ;
177
303
}
178
304
```
179
305
0 commit comments