【每日一道算法题系列】
思路:
一般我们看到子串问题,第一反应应该是滑动窗口算法,此题也不例外
主要是利用可变的滑动窗口,把我们遍历过的数据以及位置存储起来,然后通过窗口的边界,定位窗口中的数据集合
注意:
1 滑动窗口边界:当我们去判断的时候,如果没有把窗口中的数据集进行清理,那么有可能会出现边界问题,所以我们要记录窗口的边界位置。
2 Java语言中,循环中删除数据的判断问题
1 窗口数据集准确定位(定位边界,同时把非必要集合中的数据删除)
public int lengthOfLongestSubstring(String s) {
int ans = 0;
int leftOld = 0;
int leftNew = 0;
//定义滑动窗口集合
Map<Character, Integer> characters = new HashMap<>();
//循环遍历数据
for(int i = 0; i < s.length(); i++) {
//当遍历的数据在窗口中存在
if(characters.containsKey(s.charAt(i))) {
//寻找滑动窗口新的左边界
leftNew = characters.get(s.charAt(i));
//将窗口范围外左边的数据清除,从而到达一个新的左边界
for(; leftOld <= leftNew; leftOld++) {
characters.remove(s.charAt(leftOld));
}
}
//将右边界放入滑动窗口数据集合中
characters.put(s.charAt(i), i);
//寻找最大窗口数据
ans = Math.max(characters.size(), ans);
}
return ans;
}
2 不删除滑动窗口数据,只定义边界
public int lengthOfLongestSubstring(String s) {
int ans = 0;
int left = 0;
//定义滑动窗口集合
Map<Character, Integer> characters = new HashMap<>();
//循环遍历数据
for(int i = 0; i < s.length(); i++) {
//当遍历的数据在窗口中存在
if(characters.containsKey(s.charAt(i))) {
//重新定义左边界(左边界为(当前重复元素原本位置+1)与(当前左边界相比)选取最大值)
//因为没有丢弃数据,所以有可能出现数据在滑动窗口外的情况,所以需要判断
left = Math.max(left, characters.get(s.charAt(i)) + 1);
}
//新的元素放入滑动窗口中
characters.put(s.charAt(i), i);
ans = Math.max(i - left + 1, ans);
}
return ans;
}
PS: 平时写算法中,第二种算法是优质解