滑动窗口
滑动窗口是一种基于双指针思想的算法。两个指针指向的元素之间会形成一个窗口,从前往后遍历元素进行一定的运算。
无重复字符的最长字串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串的长度。
- 分析:
判断一个字符串是否存在重复字符—>新加入的字符在一个不包含重复字符的串中是否出现过。 - 方法
1.维护一个窗口,保证窗口内为不含有重复字符的子串,记录窗口的左右边界,(右边界即为当前遍历的字符下标)。
2.维护一个hash表,以字符为键,以当前该字符出现的最左位置为值。
3.窗口左边界初值为0,逐步滑动右边界,若出现了一个当前遍历过程中出现过的字符(hash表中存在),则判断该字符上一次出现的位置是否大于左边界,若大于,则更新左边界,否则说明其并不在窗口内。
4.每一次滑动后都动态计算当前窗口长度,并维护出现过的最大窗口长度。
5.返回结果。 - 也可以用整数数组来替代hash表,注意,字符串中可能存在空格、数字和字母。
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s==null||s.length()==0)
return 0;
int max_l = 1;
int cur_l = 1;
int lastindex = 0;
int[] index = new int[128]; //默认初始化值0
for (int i = 0; i < 128; i++) {
index[i] = -1;
}
index[s.charAt(0)-' ']=0;
for (int i = 1; i < s.length(); i++) {
final char c = s.charAt(i);
if(index[c-' ']!=-1){
lastindex = Math.max(index[c-' ']+1,lastindex);
}
index[c-' ']=i;
cur_l = i-lastindex+1;
max_l=Math.max(cur_l,max_l);
}
return max_l;
}
}
找到字符串中所有字母的异位词
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
- 分析
1.两个词组为异位词—>两个词的原料相同,可用一个整数数组/自定义类来表示一个字符串。
2.使用滑动窗口,大小与p相同,每次向右滑动,仅需去掉左边界字符,加上新字符即可,减少重复计算。
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
int l = p.length();
if(l>s.length()) return res;
int[] target = count(p, 0, l);
int[] count = count(s, 0, l - 1);
for (int i = 0; i < s.length()-l+1; i++) {
count[s.charAt(i+l-1)-'a']++;
if(Arrays.equals(count,target)){
res.add(i);
}
count[s.charAt(i)-'a']--;
}
return res;
}
private int[] count(String s,int start,int end){
int[] res = new int[26];
for (int i = start; i < end; i++) {
res[s.charAt(i)-'a']++;
}
return res;
}
}
- 延申
类似于计算长度为k的连续子数组的最大总和。
窗口内的最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值 。
- 分析
需要结合单调递减的双端队列
https://zhuanlan.zhihu.com/p/694074757
总结
滑动窗口方法,主要通过维护窗口内的数据,从而减少重复计算。