题目描述:
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串的长度。
第一种:暴力法,双指针(可以通过,也可以提交)
用两层for循环来遍历,使用哈希表来统计,因为哈希表可以统计出字符出现的频次,来判断什么时候子串出现了重复元素。
算法代码:
使用哈希表:
class Solution {
public int lengthOfLongestSubstring(String ss) {
int ret = 0;
int n = ss.length();
char[] s = ss.toCharArray();
// 使用 HashMap 来记录字符及其出现的次数
HashMap<Character, Integer> charCountMap = new HashMap<>();
// 第一层 for 循环从 0 开始一直到 n
for (int i = 0; i < n; i++) {
// 清空哈希表,因为我们开始一个新的子串检查
charCountMap.clear();
for (int j = i; j < n; j++) {
char c = s[j];
// 如果字符已经存在于哈希表中,则遇到了重复字符
if (charCountMap.containsKey(c)) {
break;
} else {
// 将字符添加到哈希表中
charCountMap.put(c, 1);
// 更新最大长度
ret = Math.max(ret, j - i + 1);
}
}
}
return ret;
}
}
运行结果截图:
使用数组来代替哈希表:
数组长度使用128,是因为ASCII码表的长度是128
class Solution {
public int lengthOfLongestSubstring(String ss) {
int ret = 0;
int n = ss.length();
char[] s = ss.toCharArray();
//第一层for 0开始一直到n
for (int i = 0; i < n; i++) {
//使用哈希表来记录
int[] hash = new int[128];
for (int j = i;j < n;j++){
hash[s[j]]++;
if (hash[s[j]] > 1){ //出现了重复的
break;
}else {
ret = Math.max(ret,j-i+1);
}
}
}
return ret;
}
}
运行结果:
第二种:滑动窗口
算法思路:
结果是需要连续,尝试使用滑动窗口。
判断窗口没有重复的元素。当右窗口有重复的元素,左窗口不断的出窗口,直到该重复元素的记录的数为1,然后更新结果。
主要是分成四个步骤
一、进窗口
每个元素进去窗口
二、判断
判断在窗口中有没有重复的元素
三、出窗口
有重复的元素就出窗口
四、更新结果判断
更新判断最大值的比较
算法代码:
数组长度使用128,是因为ASCII码表的长度是128
class Solution {
public int lengthOfLongestSubstring(String ss) {
char[] s = ss.toCharArray();
int ret = 0,n = ss.length(),left=0,right=0;//元素初始化
int[] has = new int[128];//通过刚刚的第一种方法可以看出,这题可以使用数组来使用
while(right<n){
has[s[right]]++;
while(has[s[right]]>1){//表示找到了重复的字串
has[s[left++]]--;//left 表示当前的
}
ret = Math.max(ret,right-left+1);
right++;
}
return ret;
}
}
运行截图: