题目:给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
Math.max()的源码
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
思路:
1、定义一个 map 数据结构存储 (k, v),其中 key 值为字符,存储有效字母,value 值为字符位置 +1,加 1 表示从字符位置后一个才开始不重复。
2、我们定义不重复子串的开始位置为 start,结束位置为 end
3、随着 end 不断遍历向后,会遇到与 [start, end] 区间内字符相同的情况,此时将字符作为 key 值,获取其 value 值,并更新 start,此时 [start, end] 区间内不存在重复字符
4、无论是否更新 start,都会更新其 map 数据结构和结果 ans。
5、时间复杂度:O(n)
图解:方便理解,复习
1、
- 第一轮循环
- 第二轮循环
- 第三轮
- 第四轮
- 第五轮
- 第六轮
public int lengthOfLongestSubstring(String s) {
int ans = 0;
HashMap<Character,Integer> map = new HashMap<>();
//存储起始点结束点。 结束条件。 必定自增的end
for (int start = 0,end = 0; end < s.length(); end++) {
char k = s.charAt(end); //获取当前数组下标的key值
if (map.containsKey(k)){
start = Math.max(map.get(k),start);//集合中如果有的话,则把start更新到重复key值所对应的下标位置
}
ans = Math.max(ans,end-start+1);// 比较最长字符串,和新串的长度,返回最长,因为start/end都为0 所以加1
map.put(s.charAt(end),end+1);
}
return ans;
}
但不是最优解,所以我看了一下评论区的大神,下面这个大神的执行用时相对较少,膜拜太猛了,最优解的网址:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/javati-jie-3wu-zhong-fu-zi-fu-de-zui-chang-zi-chua/
如果懒得点进去看的话,我把最优解的代码图解和代码放在下面
class Solution {
public int lengthOfLongestSubstring(String s) {
int i = 0;
int flag = 0;
int length = 0;
int result = 0;
while (i < s.length()) {
int pos = s.indexOf(s.charAt(i),flag);
if (pos < i) {
if (length > result) {
result = length;
}
if (result >= s.length() - pos - 1) {
return result;
}
length = i - pos - 1;
flag = pos + 1;
}
length++;
i++;
}
return length;
}
}