滑动窗口:是双指针算法的一种,可以大致理解为一个指针走的快,一个指针走的慢
算法题应用场景:
关键字:1.满足(计算结果,出现次数,包含)条件
2.最长/最短
3.子数组/子串(连续的子集)
常用模板(最大)
初始化l,r,result,bestresult
while(右指针没有到结尾){
窗口扩大,加入right对应元素,更新当前result
while(result不满足要求){
窗口缩小,移除l对应元素,l右移
}
更新最优结果bestsult
right++;
}
return bestresult;
无重复字符的最长子串
中等
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其
长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
分析:因为题目要求不重复,所以首先想到哈希表来保存,利用右指针遍历,左指针不满足不重复条件就
缩小窗口,左指针右移
时间复杂度O(n) 空间复杂度O(m)(m为set中不重复的元素)
import java.util.HashSet;
class Solution {
public int lengthOfLongestSubstring(String s) {
int len=s.length();
if(len==0)return 0;
int l=0,r=0;
int curccnt=0;
int bestcnt=0;
HashSet<Character> set=new HashSet<>();
while (r<len){
while (set.contains(s.charAt(r))){
set.remove(s.charAt(l));
l++;
}
set.add(s.charAt(r));
bestcnt=Math.max(bestcnt,set.size());
r++;
}
return bestcnt;
}
}
找到字符串中所有字母异位词
中等
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 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" 的异位词。
提示:
1 <= s.length, p.length <= 3 * 104
s
和p
仅包含小写字母
将p中的元素视为有限资源个数的“消耗品”,并统计字母个数,当“消耗品”不足,唯一可以做的就是移动左窗口释放一些出来。右指针向右遍历时,如果该元素个数大于零,将字母元素个数减一,否则左指针右移,并将元素个数加一。这样做的原因是保证左指针到右指针右侧的元素不出现字符串p以外的字母,并确保了不会超出字符串p中每个字母的最大个数。所以当长度为字符p的长度时,他们就互为字符异位词。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> list=new ArrayList<>();
int len=s.length();
int len_p=p.length();
if(len==0||len_p==0)return null;
int r=0,l=0;
char []cnt=new char[26];
for(char ch:p.toCharArray()){
cnt[ch]++;
}
while (r<len){
if(cnt[s.charAt(r)]>0){
cnt[s.charAt(r++)]--;
if(r-l==len_p)list.add(l);
}
else {
cnt[s.charAt(l++)]++;
}
}
return list;
}
}
结论:如果想要保证两个字符串满足两个条件
1,他们的字母个数相同
2,他们的都包含相同的字母
可以优先采用个数统计的方法