滑动窗口算法学习
滑动窗口算法主要应用在数组和字符串的场景中,常常可以用以解决数组或字符串的子元素问题,它可以将嵌套的循环问题,转换为单循环问题,降低时间复杂度。
1. 无重复字符的最长子串
题目描述:
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
- 暴力解决方法:
用两层循环生成所有的子串,再利用HashSet判断他们是否含有重复字符,这种方法需要的时间复杂度为O(n^3)。 - 滑动窗口算法:
我们可以构建一个滑动窗口,起始记为start,结束记为end,它们作为滑动窗口的左右边界。首先保持start位置不变,遍历字符串,如果遇到的字符不是重复的,滑动窗口增大一位,如果遇到的是重复字符,就更新滑动窗口的起始位置,更新start为重复字符的下一位,继续扫描。
同时借助一个map来判断是否有重复字符,这样就只需要一遍扫描,使算法的时间复杂度达到O(n)。
Java代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
//map的key表示字符,value为该字符的下标+1,代表该字符的后一个字符开始不重复
HashMap<Character,Integer> map = new HashMap<Character,Integer>();
//滑动窗口 起始为start,结束为i
int start = 0;
//max用来记录最长字串,也就是最后的返回结果
int max = 0;
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(map.containsKey(c))
{
start = Math.max(map.get(c)+1,start);
//更新
map.replace(c,i);
}
else
{
map.put(c,i);
}
//i-start+1即为滑动窗口的大小,也就是这一次找到的不重复字串的长度
max = Math.max(i - start + 1,max);
}
return max;
}
}
2. 实现 strStr()
题目描述:
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
输入: haystack = “hello”, needle = “ll”
输出: 2
定义一个固定大小的滑动窗口,窗口大小就是子串的长度,移动窗口,沿字符串逐一比较。
Java代码:
public int strStr(String haystack, String needle) {
//滑动窗口 起始为start,结束为start+needle.length()
int start = 0;
for(start = 0 ;start < haystack.length()-needle.length()+1;start++){
if(haystack.substring(start,start+needle.length()).equals(needle))
return start;
}
return -1;
}