3. 无重复字符的最长子串(LeetCode)
题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
条件分析
- 字符无重复;
- 子串有连续的字符构成
解题思路(滑动窗口)
- 将字符串拆分为字符数组,定义一个变量maxLen存储最长子串的长度;
- 定义两个下标left,right,如果没有重复,取maxLen为当前长度与maxLen的最大值,如果发现right和已有字符重复,则left=重复字符下标+1,right++,直到right到达末尾;
- 如何判断字符在数组中已经出现?可以考虑用一个数组freq将每个字符出现的下标记录下来,值-1代表未出现,否则存储的是元素的下标。注意在重置left的时候,老的left和新的left之间的freq元素也进行更新为-1,表示不再存在
编码如下
public int lengthOfLongestSubstring(String s) {
char[] cs = s.toCharArray();
int left = 0; // [left,right]为最大不重复子串
int right = -1;
int maxLen = 0;
int[] freq = new int[256]; // 存储元素的下标,初始情况下所有元素都不存在
for (int i=0; i<freq.length; i++) {
freq[i] = -1;
}
while (right < cs.length-1) {
right++;
// 元素不存在,计算最大值
if (freq[cs[right]] == -1) {
maxLen = max(maxLen, (right - left + 1));
} else {
// 元素存在,取出存在元素的下标+1,也就是left要移动到的新位置
int newLeft = freq[cs[right]] + 1;
// 把老的left和新的left之间的元素都设置为不存在,相当于重置
while (left < newLeft) {
freq[cs[left++]] = -1;
}
left = newLeft;
}
freq[cs[right]] = right;
}
return maxLen;
}
private int max(int max, int newMax) {
if (newMax > max) {
max = newMax;
}
return max;
}
浙公网安备 33010602011771号