1
1
/* *
2
- * Longest Substring Without Repeating Characters
3
- * ==============================================
4
- *
5
- * Leetcode: [3. Longest Substring Without Repeating Characters][lc3]
6
- *
7
- * Given a string s, find the length of the longest substring without
8
- * repeating characters.
9
- *
10
- * Tags: #strings, #medium
11
- *
12
- * Example 1:
13
- *
14
- * Input: s = "abcabcbb"
15
- * Output: 3
16
- * Explanation: The answer is "abc", with the length of 3.
17
- *
18
- * Example 2:
19
- *
20
- * Input: s = "bbbbb"
21
- * Output: 1
22
- * Explanation: The answer is "b", with the length of 1.
23
- *
24
- * Example 3:
25
- *
26
- * Input: s = "pwwkew"
27
- * Output: 3
28
- * Explanation: The answer is "wke", with the length of 3.
29
- *
30
- * Notice that the answer must be a substring, "pwke" is a subsequence and not
31
- * a substring.
32
- *
33
- * Solution
34
- * --------
2
+ * Two pointers - sliding window technique - 01
3
+ * ============================================
35
4
*
36
5
* Refer:
37
6
*
38
- * [sliding window technique][lcdi1]
39
- * [Optimized sliding window solution][ea1]
40
- *
41
- * [lc3]: https://leetcode.com/problems/longest-substring-without-repeating-characters/
42
- * [lcdi1]: https://discuss.leetcode.com/topic/30941/here-is-a-10-line-template-that-can-solve-most-substring-problems
43
- * [ea1]: https://www.enjoyalgorithms.com/blog/longest-substring-without-repeating-characters
44
- */
45
-
46
- #include < bits/stdc++.h>
47
-
48
- using namespace std ;
49
-
50
- /* ===========================================================================
51
- * Test helpers
52
- * ===========================================================================
7
+ * https://www.geeksforgeeks.org/window-sliding-technique/
8
+ * https://discuss.leetcode.com/topic/30941/here-is-a-10-line-template-that-can-solve-most-substring-problems
53
9
*/
54
- class _00_test
55
- {
56
- public:
57
- _00_test (const string &name) : name(name) {}
58
-
59
- string getName (void ) const { return name; }
60
-
61
- virtual int maxLenUniqCharsSubstr (const string &str) = 0;
62
10
63
- private:
64
- string name;
65
- };
11
+ #include " tests.h"
66
12
67
13
/* ===========================================================================
68
14
* Algorithms implementation
69
15
* ===========================================================================
70
16
*/
71
17
72
- /* TC : O(n^3)
73
- * SC : O(1)
74
- */
75
- class _01_brute_force : public _00_test
76
- {
77
- public:
78
- _01_brute_force ()
79
- : _00_test(" Longest Substring Without Repeating Characters brute "
80
- " force" )
81
- {
82
- }
83
-
84
- int maxLenUniqCharsSubstr (const string &s) override
85
- {
86
- auto is_uniq = [](string s, int b, int e) -> bool {
87
- vector m (128 , 0 );
88
- for (int k = b; k <= e; k++) {
89
- if (m[s[k]]++) return false ;
90
- }
91
- return true ;
92
- };
93
-
94
- int n = static_cast <int >(s.size ());
95
- int d = 0 ;
96
- for (int b = 0 ; b < n; b++)
97
- for (int e = b; e < n; e++)
98
- if (is_uniq (s, b, e)) d = max (d, e - b + 1 );
99
- return d;
100
- }
101
- };
102
-
103
- /* TC : O(n^2)
104
- * SC : O(1)
105
- */
106
- class _02_sliding_window : public _00_test
107
- {
108
- public:
109
- _02_sliding_window ()
110
- : _00_test(" Longest Substring Without Repeating Characters "
111
- " sliding window" )
112
- {
113
- }
114
-
115
- int maxLenUniqCharsSubstr (const string &s) override
116
- {
117
- int n = static_cast <int >(s.size ());
118
- int b = 0 , e = 0 , d = 0 ;
119
- while (b < n) {
120
- vector m (128 , 0 );
121
- e = b;
122
- while (e < n && !m[s[e]]) {
123
- d = max (d, e - b + 1 );
124
- m[s[e++]]++;
125
- }
126
- b++;
127
- }
128
- return d;
129
- }
130
- };
131
-
132
18
/* TC : O(n)
133
19
* SC : O(1)
134
20
*/
135
- class _03_optmized_sliding_window : public _00_test
136
- {
137
- public:
138
- _03_optmized_sliding_window ()
139
- : _00_test(" Longest Substring Without Repeating Characters "
140
- " optimized sliding window" )
141
- {
142
- }
143
21
144
- int maxLenUniqCharsSubstr (const string &s) override
145
- {
146
- int n = static_cast <int >(s.size ());
147
- vector m (128 , 0 );
148
- int b = 0 , e = 0 , d = 0 ;
149
- while (b < n && e < n) {
150
- if (!m[s[e]]++) {
151
- e++;
152
- d = max (d, e - b);
153
- } else
154
- m[s[b++]] = 0 ;
155
- }
156
- return d;
157
- }
158
- };
22
+ #define _2p_sw_maxSubstrUniqChars_desc " Two Pointers - Sliding Window - " \
23
+ " Longest Substring Without Repeating Characters"
159
24
160
- /* TC : O(n)
161
- * SC : O(1)
162
- */
163
- class _04_counter_sliding_window : public _00_test
25
+ int maxSubstrUniqChars (const string &s)
164
26
{
165
- public:
166
- _04_counter_sliding_window ()
167
- : _00_test(" Longest Substring Without Repeating Characters "
168
- " counter sliding window" )
169
- {
170
- }
171
-
172
- int maxLenUniqCharsSubstr (const string &s) override
173
- {
174
- vector<int > m (128 , 0 );
175
- int c = 0 , b = 0 , e = 0 , d = 0 ;
176
- while (e < static_cast <int >(s.size ())) {
177
- if (m[s[e++]]++) c++;
178
- while (c)
179
- if (m[s[b++]]-- > 1 ) c--;
180
- d = max (d, e - b);
181
- }
182
- return d;
183
- }
184
- };
27
+ int n = size (s);
28
+ int l = 0 , r = 0 , d = 0 ;
29
+ vi_v (m, 128 , 0 );
30
+ while (l < n && r < n) {
31
+ if (!m[s[r]]++) r++, d = max (d, r - l);
32
+ else m[s[l++]] = 0 ;
33
+ }
34
+ return d;
35
+ }
185
36
186
37
/* ===========================================================================
187
38
* Test code
188
39
* ===========================================================================
189
40
*/
190
- void test_impl (const vector<string> &ip, const vector<int > &op,
191
- shared_ptr<_00_test> f)
192
- {
193
- for (size_t i = 0 ; i < ip.size (); i++) {
194
- int t = f->maxLenUniqCharsSubstr (ip[i]);
195
- if (t != op[i]) {
196
- cerr << f->getName () << " test failed: "
197
- << " expected " << op[i] << " , actual " << t
198
- << " ." << endl;
199
- exit (1 );
200
- }
201
-
202
- if (getenv (" SHOW_TEST_OUTPUT" ))
203
- cout << " test-" << i << " : "
204
- << " input: str = " << ip[i]
205
- << " output: maxLen = " << t << " \n " ;
41
+ #define _2p_sw_maxSubstrUniqChars_check (i, e ) \
42
+ { \
43
+ int a = maxSubstrUniqChars (i); \
44
+ CHECK_EQ (e, a); \
45
+ SHOW_OUTPUT (i, a); \
206
46
}
207
- }
208
47
209
- int main ( int , char ** )
48
+ TEST (maxSubstrUniqChars, _2p_sw_maxSubstrUniqChars_desc )
210
49
{
211
50
vector<string> ip{" " , " abcabcbb" , " bbbbb" , " pwwkew" };
212
-
213
51
vector<int > op{0 , 3 , 1 , 3 };
214
-
215
- vector<shared_ptr<_00_test>> impls{
216
- make_shared<_01_brute_force>(),
217
- make_shared<_02_sliding_window>(),
218
- make_shared<_03_optmized_sliding_window>(),
219
- make_shared<_04_counter_sliding_window>(),
220
- };
221
-
222
- for (size_t i = 0 ; i < impls.size (); i++) {
223
- if (getenv (" SHOW_TEST_OUTPUT" ))
224
- cout << " Testing implementation " << i + 1 << " "
225
- << impls[i]->getName () << " \n " ;
226
-
227
- test_impl (ip, op, impls[i]);
228
- }
229
-
230
- cout << " Executed " << impls.size () << " implementations"
231
- << " with " << ip.size () << " tests." << endl;
232
- return 0 ;
52
+ int n = size (ip);
53
+ fii (i, n) _2p_sw_maxSubstrUniqChars_check (ip[i], op[i]);
233
54
}
55
+
56
+ INIT_TEST_MAIN ();
0 commit comments