@@ -184,4 +184,194 @@ \subsubsection{相关题目}
184
184
185
185
\begindot
186
186
\item Insert Interval,见 \S \ref {sec:insert-interval }
187
- \myenddot
187
+ \myenddot
188
+
189
+
190
+ \section {Minimum Window Substring } % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191
+ \label {sec:minimum-window-substring }
192
+
193
+
194
+ \subsubsection {描述 }
195
+ Given a string $ S$ and a string $ T$ , find the minimum window in $ S$ which will contain all the characters in $ T$ in complexity $ O(n)$ .
196
+
197
+ For example, \code {S = "ADOBECODEBANC" , T = "ABC" }
198
+
199
+ Minimum window is \code {"BANC"}.
200
+
201
+ Note:
202
+ \begindot
203
+ \item If there is no such window in $ S$ that covers all characters in $ T$ , return the emtpy string \code {""}.
204
+ \item If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in $ S$ .
205
+ \myenddot
206
+
207
+
208
+ \subsubsection {分析 }
209
+ 双指针,动态维护一个区间。尾指针不断往后扫,当扫到有一个窗口包含了所有$ T$ 的字符后,然后再收缩头指针,直到不能再收缩为止。最后记录所有可能的情况中窗口最小的
210
+
211
+
212
+ \subsubsection {代码 }
213
+ \begin {Code }
214
+ // LeetCode, Minimum Window Substring
215
+ // 双指针,动态维护一个区间。尾指针不断往后扫,当扫到有一个窗口包含了所有T的字符
216
+ // 后,然后再收缩头指针,直到不能再收缩为止。最后记录所有可能的情况中窗口最小的
217
+ class Solution {
218
+ public:
219
+ string minWindow(string S, string T) {
220
+ if (S.empty()) return "" ;
221
+ if (S.size() < T.size()) return "" ;
222
+
223
+ const int ASCII_MAX = 256;
224
+ int appeared_count[ASCII_MAX];
225
+ int expected_count[ASCII_MAX];
226
+ std::fill(appeared_count, appeared_count + ASCII_MAX, 0);
227
+ std::fill(expected_count, expected_count + ASCII_MAX, 0);
228
+
229
+ for (size_t i = 0; i < T.size(); i++) expected_count[T[i]]++;
230
+
231
+ int minWidth = INT_MAX, min_start = 0; // 窗口大小,起点
232
+ int wnd_start = 0;
233
+ int appeared = 0; // 完整包含了一个T
234
+ //尾指针不断往后扫
235
+ for (size_t wnd_end = 0; wnd_end < S.size(); wnd_end++) {
236
+ if (expected_count[S[wnd_end]] > 0) { // this char is a part of T
237
+ appeared_count[S[wnd_end]]++;
238
+ if (appeared_count[S[wnd_end]] <= expected_count[S[wnd_end]])
239
+ appeared++;
240
+ }
241
+ if (appeared == T.size()) { // 完整包含了一个T
242
+ // 收缩头指针
243
+ while (appeared_count[S[wnd_start]] > expected_count[S[wnd_start]]
244
+ || expected_count[S[wnd_start]] == 0) {
245
+ appeared_count[S[wnd_start]]--;
246
+ wnd_start++;
247
+ }
248
+ if (minWidth > (wnd_end - wnd_start + 1)) {
249
+ minWidth = wnd_end - wnd_start + 1;
250
+ min_start = wnd_start;
251
+ }
252
+ }
253
+ }
254
+
255
+ if (minWidth == INT_MAX) return "" ;
256
+ else return S.substr(min_start, minWidth);
257
+ }
258
+ };
259
+ \end {Code }
260
+
261
+
262
+ \subsubsection {相关题目 }
263
+
264
+ \begindot
265
+ \item 无
266
+ \myenddot
267
+
268
+
269
+ \section {Multiply Strings } % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270
+ \label {sec:multiply-strings }
271
+
272
+
273
+ \subsubsection {描述 }
274
+ Given two numbers represented as strings, return multiplication of the numbers as a string.
275
+
276
+ Note: The numbers can be arbitrarily large and are non-negative.
277
+
278
+
279
+ \subsubsection {分析 }
280
+ 无
281
+
282
+
283
+ \subsubsection {代码 }
284
+ \begin {Code }
285
+ /** 大整数. */
286
+ class BigInt {
287
+ public:
288
+ /**
289
+ * @brief 构造函数,将字符串转化为大整数.
290
+ * @param[in] s 输入的字符串
291
+ * @return 无
292
+ */
293
+ BigInt(string s) {
294
+ vector<int> result;
295
+ result.reserve(s.size() / RADIX_LEN + 1);
296
+
297
+ for (int i = s.size(); i > 0; i -= RADIX_LEN) { // [i-RADIX_LEN, i)
298
+ int temp = 0;
299
+ const int low = max(i - RADIX_LEN, 0);
300
+ for (int j = low; j < i; j++) {
301
+ temp = temp * 10 + s[j] - '0' ;
302
+ }
303
+ result.push_back(temp);
304
+ }
305
+ n = result;
306
+ }
307
+ /**
308
+ * @brief 将整数转化为字符串.
309
+ * @return 字符串
310
+ */
311
+ string toString() {
312
+ stringstream result;
313
+ bool started = false; // 用于跳过前导0
314
+ for (auto i = n.rbegin(); i != n.rend(); i++) {
315
+ if (started) { // 如果多余的0已经都跳过,则输出
316
+ result << std::setw(4) << std::setfill('0') << *i;
317
+ } else {
318
+ result << *i;
319
+ started = true; // 碰到第一个非0的值,就说明多余的0已经都跳过
320
+ }
321
+ }
322
+
323
+ if (!started) return "0" ; // 当x全为0时
324
+ else return result.str();
325
+ }
326
+
327
+ /**
328
+ * @brief 大整数乘法.
329
+ * @param[in] x x
330
+ * @param[in] y y
331
+ * @return 大整数
332
+ */
333
+ static BigInt multiply(const BigInt &x, const BigInt &y) {
334
+ vector<int> z(x.n.size() + y.n.size() + 1, 0);
335
+
336
+ for (size_t i = 0; i < y.n.size(); i++) {
337
+ for (size_t j = 0; j < x.n.size(); j++) { // 用y[i]去乘以x的各位
338
+ // 两数第i, j位相乘,累加到结果的第i+j位
339
+ z[i + j] += y.n[i] * x.n[j];
340
+
341
+ if (z[i + j] >= BIGINT_RADIX) { // 看是否要进位
342
+ z[i + j + 1] += z[i + j] / BIGINT_RADIX; // 进位
343
+ z[i + j] % = BIGINT_RADIX;
344
+ }
345
+ }
346
+ }
347
+ while (z.back() == 0) z.pop_back(); // 没有进位,去掉最高位的0
348
+ return BigInt(z);
349
+ }
350
+
351
+ private:
352
+ /** 一个数组元素表示4个十进制位,即数组是万进制的 */
353
+ const static int BIGINT_RADIX = 10000;
354
+ const static int RADIX_LEN = 4;
355
+ /** 万进制整数. */
356
+ vector<int> n;
357
+ BigInt(const vector<int> num) : n(num) {}
358
+ };
359
+
360
+
361
+ // LeetCode, Multiply Strings
362
+ class Solution {
363
+ public:
364
+ string multiply(string num1, string num2) {
365
+ BigInt x(num1);
366
+ BigInt y(num2);
367
+ return BigInt::multiply(x, y).toString();
368
+ }
369
+ };
370
+ \end {Code }
371
+
372
+
373
+ \subsubsection {相关题目 }
374
+
375
+ \begindot
376
+ \item 无
377
+ \myenddot
0 commit comments