滑动窗口
> 题目描述:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
> 示例 1:
输入: s = "abcabcbb"
输出: 3
> 示例 2:
> 输入: s = "bbbbb"
> 输出: 1
> 示例 3:
> 输入: s = "pwwkew"
> 输出: 3
题解思路:这是我第二次写这道题目了,卡在了与第一次同样的地方,呜呜呜难受! 这是一个滑动窗口的思想,也可以说是设定两个指针的思想:start end.
想象一个长长的窗口从数组的左边到右边进行前进,前进的同时将数组值及索引放入hashmap中,注意!不同于通常的以索引为key,以数组值为value,本题目中我们的key是数组值,value是数组索引。 一边前进,一边判断当前的数组值在hashmap中是否存在。
若存在,则说明我们遇到了重复值!此时到了滑动窗口的时刻了,我们设置int类型变量start记录滑动窗口的开头,start开始向前滑动,此时start的值=hashmap中与当前数组值相同的key所对应的value值+1;因为value 记录的索引,key是数组值
记录完start窗口就真的滑动了吗?当然不是!虽然start,也就是窗口的开头前进了,但是窗口还是原来的那个窗口,hashmap里的键值并没有改变,之前有几对,现在依旧有几对。此时我们就应该删除start之前的键值对。
我也是在这里翻车了两次,我一直用for(int i=0;i<start;i++){ hashmap.remove(chars[i]) } 此处有严重的错误,这个命令并不是删除hashmap里的start之前的键值对,这个命令删除的是chars数组中,start之前的数组值,听起来好像是一样的,但实际运行的时候,会出现这样一种情况:由于是从零开始遍历,即chars[0]可能在start窗口之后,而start之后的窗口里的值我们是不需要删除的。
因此我们需要记录下来上一次删除的位置,使用 int temp 来记录上一次删除的位置,这样遍历就从temp开始而不是从0开始了。
代码如下所示:
public int lengthOfLongestSubstring(String s) {
Map<Character,Integer> hashmap=new HashMap<>();
char[] chars=s.toCharArray();
int len=chars.length;
int max_length=0;
if(len==1)
return 1;
int temp=0;
for(int end=0,start=0;end<len;end++){
if(hashmap.containsKey(chars[end])){
start = hashmap.get(chars[end])+1;
for(int i=temp;i<start;i++)
hashmap.remove(chars[i]);//注意此处
temp=start;
}
hashmap.put(chars[end],end);
if(end-start+1>max_length){
max_length=end-start+1;
}
}
return max_length;
}