给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1. 都能想到,最简单的。 我认为是冒泡排序思想
/**
* 应该算是冒泡排序
*
* @param s
* @return
*/
public static int lengthOfLongestSubstring(String s) {
if (StringUtils.isBlank(s)) {
throw new IllegalArgumentException("参数不能为空");
}
char[] chars = s.toCharArray();
int max = 1;
for (int i = 0; i < chars.length; i++) {
String temp = "";
temp += chars[i];
for (int j = i + 1; j < chars.length; j++) {
if (temp.contains(chars[j] + "")) {
break;
}
temp += chars[j];
}
if (temp.length() > max) {
max = temp.length();
}
}
return max;
}
2. 发现的套路,使用 map,list, set 或其他数据结构 来装载中间变量。 将时间复杂度降低都是以空间换时间 ,我前面写的一篇文章,就是使用map结构
leetCode 给定数组,目标值 计算数组下标_qq_33919114的博客-CSDN博客
第二种解法: 使用滑动窗口
什么是滑动窗口?
其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!
如何移动?
我们只要把队列的左边的元素移出就行了,直到满足题目要求!
一直维持这样的队列,找出队列出现最长的长度时候,求出解!
时间复杂度:O(n)
public static int lengthOfLongestSubstring2(String s) {
if (StringUtils.isBlank(s)) {
throw new IllegalArgumentException("参数不能为空");
}
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
2.2 滑动窗口set 版, 滑动窗口思想 left, right
public static int lengthOfLongestSubstring4(String s) {
Set<Character> set = new HashSet<>();
int left = 0, res = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
while (!set.add(c)) {
set.remove(s.charAt(left++));
}
res = Math.max(res, i - left + 1);
}
return res;
}
3. 滑动窗口 b站视频