我真的会动之滑动窗口

最近在整理之前刷过的********题目,想写写一些常见的、典型的解题技巧或者方法。于是我想介绍一下滑动窗口方法。

1.无重复字符的最长子串

/*给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 */

#include<iostream>
#include<unordered_map>
#include<string>

using namespace std;

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
         int n=s.size();
        int right=-1,ans=0;
        unordered_set<char> dp;
        for(int i=0;i<n;++i)
        {
            if(i!=0)
            {
                dp.erase(s[i-1]);
            }
            while(right+1<n&&!dp.count(s[right+1]))
            {
                dp.insert(s[right+1]);
                ++right;
            }
            ans=max(ans,right-i+1);
        }
        return ans;
    }
};

int main() {
    string s;
    cin >> s;
    Solution so1;
    int ans = so1.lengthOfLongestSubstring(s);
    cout << ans << endl;
    return 0;
}

2.最小覆盖子串

/*给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。

示例:

输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"*/


#include<iostream>
#include<unordered_map>
#include<string>

using namespace std;

class Solution {
public:
	string minWindow(string s, string t) {
		if (t.size() == 0 || s.size() == 0) return "";

		unordered_map<char, int> m_t;
		unordered_map<char, int> window;
		for (int i = 0; i < t.size(); i++) m_t[t[i]]++;

		int left = 0, right = 0;
		int start = 0, minlen = INT_MAX;
		int match = 0;

		while (right < s.size()) {
			char c1 = s[right];
			if (m_t.count(c1)) {
				window[c1]++;
				if (window[c1] == m_t[c1]) {
					match++;
				}
			}
			right++;

			while (match == m_t.size()) {
				char c2 = s[left];
				if (right - left < minlen) {
					start = left;
					minlen = right - left;
				}
				if (m_t.count(c2)) {
					window[c2]--;
					if (window[c2] < m_t[c2]) {
						match--;
					}
				}
				left++;
			}
		}

		return minlen == INT_MAX ? "" : s.substr(start, minlen);
	}
};

int main() {
	string s, t;
	cin >> s >> t;

	Solution so1;
	string ans = so1.minWindow(s, t);
	cout << ans << endl;
	return 0;
}

3.找到字符串中所有字母异位词

/*给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。

说明:

字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
示例 1:

输入:
s: "cbaebabacd" p: "abc"

输出:
[0, 6]*/

#include<iostream>
#include<unordered_map>
#include<string>

using namespace std;

class Solution {
public:

	vector<int> findAnagrams(string s, string p) {
		vector<int> ans;
		if (s.size() == 0) return ans;

		unordered_map<char, int> m_p;
		unordered_map<char, int> window;
		int left = 0, right = 0;

		int match = 0;

		for (int i = 0; i < p.size(); i++) m_p[p[i]]++;

		while (right < s.size()) {
			char c1 = s[right];
			if (m_p.count(c1)) {
				window[c1]++;
				if (window[c1] == m_p[c1]) {
					match++;
				}
			}
			right++;

			while (match == m_p.size()) {
				char c2 = s[left];
				if (right - left == p.size()) {
					ans.push_back(left);
				}
				if (m_p.count(c2)) {
					window[c2]--;
					if (window[c2] < m_p[c2]) {
						match--;
					}
				}
				left++;
			}
		}

		return ans;
	}
};

int main() {
	string s, p;
	cin >> s >> p;
	Solution so1;

	vector<int> ans = so1.findAnagrams(s, p);
	for (int i = 0; i < ans.size(); i++) {
		printf("%d ", ans[i]);
	}
	printf("\n");
	return 0;
}

下面的这个地址有十分详细的解答过程,我就不献丑了。 le地址

Leetcode刷题整合 文章被收录于专栏

都是作者刷到的一些感觉是好题整理到一起的,辛苦整理不易,麻烦给个赞,有疑问请留言

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务