感谢微信公众号 labuladong的滑动窗口模板,真的好用,下边是利用模板做了六道题
第一题 3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是"abc",所以其
长度为 3。示例 2:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是"b"
,所以其长度为 1。示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.empty()) return 0;
unordered_map<char, int> window;
int left = 0, right = 0;
int res = 0;
while (right < s.size()) {
char c = s[right];
right++;
window[c]++;
while (window[c] > 1) {
char d = s[left];
left++;
window[d]--;
}
res = max(res, right - left);
}
return res;
}
};
第二题 30. 串联所有单词的子串
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入: s = "barfoothefoobarman", words = ["foo","bar"] 输出:[0,9]
解释: 从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。 输出的顺序不重要, [9,0] 也是有效答案。示例 2:
输入: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]输出:[]
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> res;
if (words.empty()) return res;
unordered_map<string, int> need;
for (string s : words) need[s]++;
int len = words[0].size();
int n = words.size();
for (int i = 0; i < len; i ++) {
int left = i, right = i;
int valid = 0;
unordered_map<string, int> window;
while (right < s.size()) {
string word = s.substr(right, len);
right += len;
if (need.count(word)) {
window[word]++;
if (window[word] == need[word]) {
valid++;
}
}
while (right - left >= n * len) {
if(valid == need.size()) {
res.push_back(left);
}
string str = s.substr(left, len);
left += len;
if (need.count(str)) {
if (need[str] == window[str]) {
valid--;
}
window[str]--;
}
}
}
}
return res;
}
};
第三题 76. 最小覆盖子串
给你一个字符串
s
、一个字符串t
。返回s
中涵盖t
所有字符的最小子串。如果s
中不存在涵盖t
所有字符的子串,则返回空字符串""
。注意:如果
s
中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC"示例 2:
输入:s = "a", t = "a" 输出:"a"
提示:
1 <= s.length, t.length <= 105
s
和t
由英文字母组成
class Solution {
public:
string minWindow(string s, string t) {
if (s.empty()) return "";
unordered_map<char, int> need;
unordered_map<char, int> window;
for (char c : t) need[c]++;
int left = 0, right = 0;
int valid = 0;
string res = "";
while (right < s.size()) {
char c = s[right];
right++;
if (need.count(c)) {
window[c]++;
if (window[c] == need[c]) {
valid++;
}
}
while (valid == need.size()) {
if (res.empty() || res.size() >= right - left) {
res = s.substr(left, right - left);
}
char d = s[left];
left++;
if (need.count(d)) {
if (need[d] == window[d]) {
valid--;
}
window[d]--;
}
}
}
return res;
}
};
第四题 209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
进阶:
如果你已经完成了 O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
if (nums.empty()) return 0;
int n = nums.size();
int res = nums.size() + 1;
int sum = 0, left = 0, right = 0;
while (right < nums.size()) {
sum += nums[right];
right++;
while (sum >= s) {
res = min(res, right - left);
sum -= nums[left];
left++;
}
}
return res == nums.size() + 1 ? 0 : res;
}
};
第五题 438. 找到字符串中所有字母异位词
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:
字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。示例 1:
输入:
s: "cbaebabacd" p: "abc"输出:
[0, 6]解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。示例 2:
输入:
s: "abab" p: "ab"输出:
[0, 1, 2]解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> res;
unordered_map<char, int> need;
unordered_map<char, int> window;
for (char c : p) need[c]++;
int n = s.size();
int left = 0, right = 0;
int valid = 0;
while (right < n) {
char c = s[right];
right++;
if (need.count(c)) {
window[c]++;
if (window[c] == need[c]) {
valid++;
}
}
while (right - left >= p.size()) {
if (valid == need.size()) {
res.push_back(left);
}
char d = s[left];
left++;
if (need.count(d)) {
if (window[d] == need[d]) {
valid--;
}
window[d]--;
}
}
}
return res;
}
};
第六题 567. 字符串的排列
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
示例2:
输入: s1= "ab" s2 = "eidboaoo"
输出: False
注意:
输入的字符串只包含小写字母
两个字符串的长度都在 [1, 10,000] 之间来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-in-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public:
bool checkInclusion(string t, string s) {
unordered_map<char, int> need, window;
for (char c : t) need[c]++;
int left = 0, right = 0;
int valid = 0;
while (right < s.size()) {
char c = s[right];
right++;
if (need.count(c)) {
window[c]++;
if (need[c] == window[c]) {
valid++;
}
}
while (right - left >= t.size()) {
if (valid == need.size()) {
return true;
}
char d = s[left];
left++;
if (need.count(d)) {
if (need[d] == window[d]) {
valid--;
}
window[d]--;
}
}
}
return false;
}
};