1.基本概念
利用单调性,使用同向双指针,两个指针之间形成一个窗口
- 子串与子数组都是连续的一段
- 子序列时不连续的
2.为什么可以用滑动窗口?
暴力解决时发现两个指针不需要回退(没必要回退,一定不会符合结果)也可以解决当前的问题,此时就可以使用滑动窗口
3.实际应用
1.无重复字符的最长子串
1.题目要求
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
2.解题思路
- 首先此题是要求得子串,并且是最长的无重复字符,
- 最容易想到的就是暴力解法,遍历所有的子串,通过数组模拟哈希表来判断是否重复,此时时间复杂度为o(n2)级别
- 但是此时有一个更优解,如果右边的指针遇到了重复值,那么从重复的前一个值开始左边的值都不可能存在比当前长度更长的答案了,此时我们就可以直接从重复的前一个值的下一个字符出发判断,此时right继续往后判断即可,此时时间复杂度为o(n)级别
3.解题步骤
- left = 0, right = 0
- 进窗口,当前字符加入窗口
- 判断,若当前字符并未重复,则right++
- 出窗口,若字符重复,依次出窗口,left++,直至无重复
- 更新结果,当字符成功加入窗口时,就可以更新结果
- 结束条件:right指针移动到最右边位置时
4.解题代码:
public int lengthOfLongestSubstring(String s) {
int[] hash = new int[128];
char[] ch = s.toCharArray();
int ret = 0;
for (int left = 0, right = 0; right < s.length(); right++) {
// 进窗口
hash[ch[right]]++;
while (hash[ch[right]] > 1) {
// 出现重复
//出窗口
hash[ch[left]]--;
left++;
}
ret = Math.max(ret, right - left + 1);
}
return ret;
}