题目
无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
错误过程
勿用,效率极差
public int lengthOfLongestSubstring(String s) {
int num=0;
int len=0;
List list=new ArrayList();
char[] str =s.toCharArray();
for(int i=0;i<str.length;i++){
if (list.contains(str[i])){
int k=list.size();
if(len<k)
len=k;
num=list.indexOf(str[i]);
int x=num;
for(int j=0;j<=x;){
list.remove(j);
x--;
}
}
list.add(str[i]);
if(i==str.length-1){
if(len<list.size()){
len=list.size();
}
}
}
if (len == 0) {
len=list.size();
}
return len;
}
最初想:设置一个ArrayList,将String s转换成char[]数组,然后一个个加入,在加入数组的过程中比较数组前面的元素,存在相同的就去掉前面的子串(0到第一个相同元素)
在实现过程中出了各种各样的错误
remove方法每次删除都会把序号向前移,导致需要设置一个信号x
num=list.indexOf(str[i]);
int x=num;
for(int j=0;j<=x;){
list.remove(j);
x--;
}
没有重复,也就不进入去子串过程,需要多一句判断
if (len == 0) {
len=list.size();
}
如果“aab”这种字符串,去子串后的子串最长,又需要判断
if(i==str.length-1){
if(len<list.size()){
len=list.size();
}
}
效率极差,还花了这么多时间考虑,当然,比暴力解法要好一些
这就是刚碰LeetCode狼狈的样子,还需学习
后面看了官方的方法,原来我这个本质上也是滑动窗口法,只是不够系统
官方的方法 - 滑动窗口
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>(); // current index of character
// try to extend the range [i, j]
for (int j = 0, i = 0; j < n; j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i);
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j), j + 1);
}
return ans;
}
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-leetcod/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
设置一个Map,Map的key放字符,value放该字符所在数组下标
如果下一个字符在[i,j]找到重复的,将{i,map.get(s.charAt(j))}中大的那个替代i,也就是窗口滑动
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i);
}
ans表示数组的大小,也就是无重复字符的最长子串
ans = Math.max(ans, j - i + 1);