链接
LeetCode题目:https://leetcode.com/problems/minimum-window-substring/
难度:Hard
题目
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).
For example,
S = “ADOBECODEBANC”
T = “ABC”
Minimum window is “BANC”.
分析
这题的难点在于时间复杂度要在O(n),而暴力或者动态规划需要的时间复杂度都在O(n^2)以上,所以考虑用贪心算法。
具体做法是用双指针动态维护匹配的字符串区间,尾指针不断移动,当匹配成功且实际匹配数大于预期匹配时可以移动头指针,并用另外2个变量记录匹配到的最短字符串开头下标以及长度。
代码
#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
using namespace std;
class Solution {
public:
string minWindow(string s, string t) {
auto t_set = get_t_set(t);
auto t_pos = get_t_pos(s, t_set);
auto expect_cnt_map = get_expect_cnt_map(t);
auto match_cnt_map = get_match_cnt_map(t);
if (s.size() < t.size()) return "";
if (t.size() == 0) return "";
int min_len = INT32_MAX, min_start = 0;
int left_pos = 0;
int match_cnt = 0;
for (int right_pos = 0; right_pos < t_pos.size(); right_pos++) {
char right_c = s[t_pos[right_pos]];
match_cnt_map[right_c] += 1;
if (match_cnt_map[right_c] <= expect_cnt_map[right_c]) {
match_cnt++;
}
if (match_cnt == t.size()) {
while (match_cnt_map[s[t_pos[left_pos]]] > expect_cnt_map[s[t_pos[left_pos]]]) {
match_cnt_map[s[t_pos[left_pos]]] -= 1;
left_pos++;
}
int match_len = t_pos[right_pos] - t_pos[left_pos] + 1;
if (match_len < min_len) {
min_len = match_len;
min_start = left_pos;
}
}
}
if (min_len == INT32_MAX) return "";
else return s.substr((unsigned long) t_pos[min_start], (unsigned long) min_len);
}
private:
unordered_set<char> get_t_set(string t) {
unordered_set<char> t_set;
for (auto c:t) {
t_set.insert(c);
}
return t_set;
}
vector<int> get_t_pos(string s, unordered_set<char> t_set) {
vector<int> t_pos;
for (int i = 0; i < s.size(); i++) {
if (t_set.find(s[i]) != t_set.end()) {
t_pos.push_back(i);
}
}
return t_pos;
}
unordered_map<char, int> get_expect_cnt_map(string t) {
unordered_map<char, int> cnt_map;
for (auto c:t) {
if (cnt_map.find(c) == cnt_map.end()) {
cnt_map.insert({c, 1});
} else {
cnt_map[c] += 1;
}
}
return cnt_map;
};
unordered_map<char, int> get_match_cnt_map(string t) {
unordered_map<char, int> cnt_map;
for (auto c:t) {
cnt_map[c] = 0;
}
return cnt_map;
};
};