diff --git a/include/s0076_minimum_window_substring.hpp b/include/s0076_minimum_window_substring.hpp new file mode 100644 index 0000000..f085698 --- /dev/null +++ b/include/s0076_minimum_window_substring.hpp @@ -0,0 +1,16 @@ +#ifndef S0076_MINIMUM_WINDOW_SUBSTRING_HPP +#define S0076_MINIMUM_WINDOW_SUBSTRING_HPP + +#include +#include + +using namespace std; + +class Solution { + public: + string minWindow(string s, string t); + unordered_map ori, cnt; + bool check(); +}; + +#endif diff --git a/include/s0209_minimum_size_subarray_sum.hpp b/include/s0209_minimum_size_subarray_sum.hpp new file mode 100644 index 0000000..9477e10 --- /dev/null +++ b/include/s0209_minimum_size_subarray_sum.hpp @@ -0,0 +1,14 @@ +#ifndef S0209_MINIMUM_SIZE_SUBARRAY_SUM_HPP +#define S0209_MINIMUM_SIZE_SUBARRAY_SUM_HPP + +#include +#include + +using namespace std; + +class Solution { + public: + int minSubArrayLen(int target, vector& nums); +}; + +#endif diff --git a/notes/src/SUMMARY.md b/notes/src/SUMMARY.md index 50acb15..af4619f 100644 --- a/notes/src/SUMMARY.md +++ b/notes/src/SUMMARY.md @@ -2,6 +2,7 @@ - [二分查找](./bin_search.md) - [移除元素](./remove_elements.md) +- [长度最小的子数组](./minimum_size_subarray_sum.md) # 经典代码 diff --git a/notes/src/minimum_size_subarray_sum.md b/notes/src/minimum_size_subarray_sum.md new file mode 100644 index 0000000..131d70d --- /dev/null +++ b/notes/src/minimum_size_subarray_sum.md @@ -0,0 +1,20 @@ +# 长度最小的子数组 + +当题目中含有: + +- 数组 +- 连续子数组 + +这两个关键词时,考虑使用非定长滑动窗口(即长度不固定的滑动窗口) + +这种滑动窗口有两个关键: + +- 起始指针,什么条件下移动 +- 终止指针,什么条件下移动 + +想清楚这两个问题就可以解答了。 + +## 相关题目 + +- [209. 长度最小的子数组](https://leetcode.com/problems/minimum-size-subarray-sum/) +- [76. 最小覆盖子串](https://leetcode.com/problems/minimum-window-substring/) diff --git a/src/s0076_minimum_window_substring.cpp b/src/s0076_minimum_window_substring.cpp new file mode 100644 index 0000000..355a10d --- /dev/null +++ b/src/s0076_minimum_window_substring.cpp @@ -0,0 +1,39 @@ +#include "s0076_minimum_window_substring.hpp" + +bool Solution::check() { + for (const auto &p : ori) { + if (cnt[p.first] < p.second) { + return false; + } + } + return true; +} + +// 不包含 t 中所有字符,r 右移 +// 包含 t 中所有字符,l 右移 +string Solution::minWindow(string s, string t) { + for (const auto &c : t) { + ++ori[c]; + } + + int l = 0, r = -1; + int len = INT_MAX, ansL = -1, ansR = -1; + + while (r < int(s.size())) { + if (ori.find(s[++r]) != ori.end()) { + ++cnt[s[r]]; + } + while (check() && l <= r) { + if (r - l + 1 < len) { + len = r - l + 1; + ansL = l; + } + if (ori.find(s[l]) != ori.end()) { + --cnt[s[l]]; + } + ++l; + } + } + + return ansL == -1 ? string() : s.substr(ansL, len); +} diff --git a/src/s0209_minimum_size_subarray_sum.cpp b/src/s0209_minimum_size_subarray_sum.cpp new file mode 100644 index 0000000..ef0195c --- /dev/null +++ b/src/s0209_minimum_size_subarray_sum.cpp @@ -0,0 +1,32 @@ +#include "s0209_minimum_size_subarray_sum.hpp" + +int Solution::minSubArrayLen(int target, vector& nums) { + int len = nums.size(); + int result{INT_MAX}; + for (int begin{0}, end{0}, sum{0}; end < len; ++end) { + sum += nums[end]; + // 当滑动窗口里的值的总和大于等于 target 时,移动 begin 直到 sum 比 target + // 小 + if (sum >= target) { + while (begin < end && sum >= target) { + sum -= nums[begin]; + ++begin; + } + // 循环结束后有以下几种情况 + // 1. begin == end && sum >= target 此时 result == 1 + // 2. begin == end && sum < target 此时 result == 2 + // 3. begin < end && sum < target 此时 result == end - begin + 2 + int tmp; + if (begin == end) { + tmp = sum >= target ? 1 : 2; + } else { + tmp = end - begin + 2; + } + // 更新 result + result = tmp < result ? tmp : result; + } + } + // 如果 result == INT_MAX 说明 result + // 从来没更新过,也就意味着即使所有数组元素加在一起也比 target 小,此时返回 0 + return result == INT_MAX ? 0 : result; +} diff --git a/tests/s0076_minimum_window_substring.cpp b/tests/s0076_minimum_window_substring.cpp new file mode 100644 index 0000000..08ddc53 --- /dev/null +++ b/tests/s0076_minimum_window_substring.cpp @@ -0,0 +1,27 @@ +#include "s0076_minimum_window_substring.hpp" + +#include + +TEST(Problem76, Case1) { + string s{"ADOBECODEBANC"}; + string t{"ABC"}; + string expected{"BANC"}; + Solution solution; + EXPECT_EQ(solution.minWindow(s, t), expected); +} + +TEST(Problem76, Case2) { + string s{"a"}; + string t{"a"}; + string expected{"a"}; + Solution solution; + EXPECT_EQ(solution.minWindow(s, t), expected); +} + +TEST(Problem76, Case3) { + string s{"a"}; + string t{"aa"}; + string expected{""}; + Solution solution; + EXPECT_EQ(solution.minWindow(s, t), expected); +} diff --git a/tests/s0209_minimum_size_subarray_sum.cpp b/tests/s0209_minimum_size_subarray_sum.cpp new file mode 100644 index 0000000..edeb553 --- /dev/null +++ b/tests/s0209_minimum_size_subarray_sum.cpp @@ -0,0 +1,35 @@ +#include "s0209_minimum_size_subarray_sum.hpp" + +#include + +TEST(Problem209, Case1) { + int target{7}; + vector nums{2, 3, 1, 2, 4, 3}; + int o{2}; + Solution solution; + EXPECT_EQ(solution.minSubArrayLen(target, nums), o); +} + +TEST(Problem209, Case2) { + int target{4}; + vector nums{1, 4, 4}; + int o{1}; + Solution solution; + EXPECT_EQ(solution.minSubArrayLen(target, nums), o); +} + +TEST(Problem209, Case3) { + int target{11}; + vector nums{1, 1, 1, 1, 1, 1, 1, 1}; + int o{0}; + Solution solution; + EXPECT_EQ(solution.minSubArrayLen(target, nums), o); +} + +TEST(Problem209, Case4) { + int target{11}; + vector nums{1, 2, 3, 4, 5}; + int o{3}; + Solution solution; + EXPECT_EQ(solution.minSubArrayLen(target, nums), o); +}