题目描述:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
示例一:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例二:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例三:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
题解一 暴力法:
定义record记录重复字符的位置,初始置为0。依次判断当前字符与当前字符之前record位置之后的字符串是否相等,
public int lengthOfLongestSubstring(String s) {
if(s.length()==0||s==null)
return 0;
int maxLen=1,record=0;
for(int i=1;i<s.length();i++) {
int len=1;
for(int j=i-1;j>=record;j--) {
if(s.charAt(i)==s.charAt(j)) {
record=j+1;
break;
}
else
len++;
}
maxLen=Math.max(maxLen, len);
}
return maxLen;
}
题解二 滑动窗口:
定义一个滑动窗口,记录当前子串的起始位置和结束位置,并将当前子串加入集合中。每次向集合中添加字符时首先判断该字符是否在集合中已经存在,若存在则滑动窗口区间的起始点向前移动一个位置,在移动之前将重复字符移除,直至结束。
一步步向前滑,直到集合中不存在该字符时,再将该字符插入集合并更新j
public int lengthOfLongestSubstring(String s) {
int len=0;
Set<Character> sub=new HashSet<>();
int i=0,j=0;
while(i<s.length()&&j<s.length()) {
if(sub.contains(s.charAt(j))) {
sub.remove(s.charAt(i++));
}else{
sub.add(s.charAt(j));
j++;
len=Math.max(len, j-i);
}
}
return len;
}
题解三 优化的滑动窗口:
优化的滑动窗口是在滑动窗口的基础上,每次滑动窗口区间[i,j)中的i向前移动时移动的位置个数大于等于1。
定义一个滑动窗口,记录无重复字符的子串的起始位置和结束位置,即[i,j),将该窗口内的字符以及该字符在数组中的下标存入集合map中,新来的字符首先判断map中是否已经存在,若不存在则j加1,并更新无重复子串的长度;反之获取当前字符的位置k,更新i=math.max(k+1,i),之所以k+1和i取最大,是为了防止获取的后一个添加的重复字符的下标比前一个添加的重复字符的下标要小,即字符串为abba这种情况。
[i,j)区间永远记录无重复的子串,但当前区间并不一定对应的是最长的无重复子串。
(子串,不重复,区间,跳跃)
跳跃式的滑动,当前更新后的i到j之间不存在与将插入的字符重复的元素。
public int lengthOfLongestSubstring(String s) {
int len=0;
Map<Character,Integer> sub=new HashMap<>();
int i=0,j=0;
while(i<s.length()&&j<s.length()) {
if(sub.containsKey(s.charAt(j))) {
//应该保证滑动窗口的起始位置依次向前,不能倒退
i=Math.max(i, sub.get(s.charAt(j))+1);//Math.max的作用 :考虑字符串abba这个例子
}
sub.put(s.charAt(j), j);
j++;
len=Math.max(len, j-i);
}
return len;
}
1869

被折叠的 条评论
为什么被折叠?



