https://leetcode.cn/problems/longest-substring-without-repeating-characters/
题目描述
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
解题思路
暴力
暴力枚举 + hash表(判断字符是否出现)
优化算法
利用滑动窗口求解
1.定义left,right指针,都向右滑动,left,right初始值为0
2.利用哈希表存储最长无重复数组,right每次向右移动之前,都将当前指向的字符和在哈希表中寻找有没有对应的,如果有,则移动left,否则,将right指向的当前字符存入哈希表,然后right++,直到遇到重复的字符
3.每次left移动之前,要计算hash表的长度,与原来的长度比较,如果大于原来的长度,则更新len,如果小于,则什么都不干,直到right到达数组的最后,返回len
注:hash表可以用整型数组代替,整型数组的长度为128,将每次的字符的ascll码作为数组的下标,如果num[right] 等于0,代表哈希表中没有重复元素,然后将此位置元素改为1;如果等于1则代表哈希表中已有此元素,left向右移动合适的位置
代码
public int lengthOfLongestSubstring(String s) {
//定义一个整型数组,代替hash表
int[] num = new int[128];
//定义左右指针,代表滑动窗口的边界
int left = 0;
int right = 0;
int len = 0; //子串的长度
while (right<s.length()){ // right到达字符串的最右边停止循环
//判断当前哈希表中有没有right所指的字符
if (right<s.length() && num[s.charAt(right)] == 0){ //没有,则将字符存入哈希表,数组改为1,接着移动right
num[s.charAt(right)] = 1; // 将字符存入哈希表
right++;
//移动一次更新一次len
if (len<(right-left)){
len = right-left;
}
}else { //如果存在,移动left到合适的位置
while (s.charAt(left)!=s.charAt(right)){ //将哈希表中重复字符的左边的字符弹出哈希表
num[s.charAt(left)] = 0;
left++;
}
num[s.charAt(left)] = 0; //将哈希表中的重复字符弹出
left++;
}
}
return len;
}