Minimum Size Subarray Sum

This commit is contained in:
Sainnhe Park 2022-11-29 18:25:47 +08:00
parent 1e65cff7e5
commit 80ee14486c
8 changed files with 184 additions and 0 deletions

View File

@ -0,0 +1,16 @@
#ifndef S0076_MINIMUM_WINDOW_SUBSTRING_HPP
#define S0076_MINIMUM_WINDOW_SUBSTRING_HPP
#include <string>
#include <unordered_map>
using namespace std;
class Solution {
public:
string minWindow(string s, string t);
unordered_map<char, int> ori, cnt;
bool check();
};
#endif

View File

@ -0,0 +1,14 @@
#ifndef S0209_MINIMUM_SIZE_SUBARRAY_SUM_HPP
#define S0209_MINIMUM_SIZE_SUBARRAY_SUM_HPP
#include <vector>
#include <climits>
using namespace std;
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums);
};
#endif

View File

@ -2,6 +2,7 @@
- [二分查找](./bin_search.md) - [二分查找](./bin_search.md)
- [移除元素](./remove_elements.md) - [移除元素](./remove_elements.md)
- [长度最小的子数组](./minimum_size_subarray_sum.md)
# 经典代码 # 经典代码

View File

@ -0,0 +1,20 @@
# 长度最小的子数组
当题目中含有:
- 数组
- 连续子数组
这两个关键词时,考虑使用非定长滑动窗口(即长度不固定的滑动窗口)
这种滑动窗口有两个关键:
- 起始指针,什么条件下移动
- 终止指针,什么条件下移动
想清楚这两个问题就可以解答了。
## 相关题目
- [209. 长度最小的子数组](https://leetcode.com/problems/minimum-size-subarray-sum/)
- [76. 最小覆盖子串](https://leetcode.com/problems/minimum-window-substring/)

View File

@ -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);
}

View File

@ -0,0 +1,32 @@
#include "s0209_minimum_size_subarray_sum.hpp"
int Solution::minSubArrayLen(int target, vector<int>& 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;
}

View File

@ -0,0 +1,27 @@
#include "s0076_minimum_window_substring.hpp"
#include <gtest/gtest.h>
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);
}

View File

@ -0,0 +1,35 @@
#include "s0209_minimum_size_subarray_sum.hpp"
#include <gtest/gtest.h>
TEST(Problem209, Case1) {
int target{7};
vector<int> 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<int> nums{1, 4, 4};
int o{1};
Solution solution;
EXPECT_EQ(solution.minSubArrayLen(target, nums), o);
}
TEST(Problem209, Case3) {
int target{11};
vector<int> 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<int> nums{1, 2, 3, 4, 5};
int o{3};
Solution solution;
EXPECT_EQ(solution.minSubArrayLen(target, nums), o);
}