题目描述:
给定一个字符串 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 由英文字母、数字、符号和空格组成
1、思路分析:(低级版,效率低200ms)
遍历字符串s对应的字符集合,(只有字符串长度大于0的情况才能进入for循环遍历否则将会返回默认值0)
变量left用于记录窗口最左边字符的脚标
变量s1用于记录窗口内的字符串
每遇到一个未重复的字符记录值count++;遇到一个重复出现的字符则left+1,且i=letf,窗口将重新从letf开始检测
class Solution {
public int lengthOfLongestSubstring(String s) {
String s1="";
int left=0;
int max_size=0;
int count=0;
for (int i = 0; i < s.length(); i++) {
s1=s.substring(left,i);
if (s1.contains(s.substring(i,i+1))){
left++;
i=left;
count=1;
}else {
count++;
}
max_size=count>max_size?count:max_size;
}
return max_size;
}
}
2、思路分析:(进阶版4ms)
依旧是窗口思想的实现
遍历字符串s对应的字符集合,将每一个遇到的字符添加到map集合中,已经存在的键根据map集合的特点将会更新其值。
map集合中key为遇到的字符,对应的值为它目前对应的在字符串s中的位数(值为字符数组脚标+1)
left用于记录窗口最左边字符的在字符串中的位数
class Solution {
public int lengthOfLongestSubstring(String s) {
int max_length = 0;
int left=0;
HashMap<Character, Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
left=map.containsKey(s.charAt(i))?Math.max(map.get(s.charAt(i)),left):left;
max_length=Math.max(max_length,i-left+1);
map.put(s.charAt(i),i+1);
}
return max_length;
}
}
3、思路分析(进阶版plus 1ms)
定义一个128大小的数组,依据字符对应的ASCII码进行查找
利用数组存取值速度快于map取值的特点,改进上面算法的实现,使得算法执行效率进一步提高
//高阶版
class Solution {
public int lengthOfLongestSubstring(String s) {
int fa = 0;
int [] map = new int[128];
char [] ch = s.toCharArray();
//if(s.length()==1)return 1;
for (int j = 0, i = 0; j < s.length(); j++) {
i = Math.max(map[ch[j]],i);
fa = Math.max(fa,j-i+1);
map[ch[j]] = j +1 ;
}
return fa;
}
}