题目:字符串不含重复字符的最长子串
/* 给定一个字符串 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 由英文字母、数字、符号和空格组成 Related Topics 哈希表 字符串 滑动窗口*/
思路:快慢指针思想
慢指针指向子字符串的起始位置,快指针指向子字符串的结束位置
如果当前子字符串不包含重复字符,就比较当前最长不重复子串长度与当前子串的长度,取最大的值
如果当前子串包含重复字符,则将慢指针指向前移动一位。此时快指针和慢指针之间的字符都是没有重复字符的
例如 abcbb,慢指针slow指向0,快指针指向2时,当前最长不重复子串,就取 max(2,"abc".length()
当快指针指向3时,发现有重复元素b,就将慢指针向前移动一位,此时"bcb",然后判断仍旧有重复元素,慢指针继续向前移动,“cb"
public static int getMaxLength(String s) {
int maxLen = 0;
HashSet<Character> set = new HashSet<>();
char[] charArray = s.toCharArray();
int slow = 0;
String s1 = "";
for (int i = 0; i < charArray.length; i++) {
s1 = s.substring(slow, i + 1);
//如果s1不包含重复字符
if (!isContainsRepeateWord(s1)) {
maxLen = Math.max(maxLen, s1.length());
} else {
slow++;
}
}
return maxLen;
}
public static boolean isContainsRepeateWord(String s) {
HashSet<Character> set = new HashSet<>();
char[] charArray = s.toCharArray();
for (char c : charArray) {
set.add(c);
}
if (set.size() == s.length()) {
//不包含
return false;
}
//包含
return true;
}
方法二
用set维护当前最长不重复子串
维护左指针和右指针,当set中不包含该字符时,先将不重复字符添加到set中,然后右指针移动一位
否则有重复的字符,先删除set中左指针位置的元素,左指针移动,
如abcbb,刚开始left=0,right =0,1,2时,set依次添加元素 a,b,c
当right=3时,包含重复元素b,此时left=0,先将set中0元素删除,set中元素是b,c,然后left++,left=1,然后还有重复字符b,此时s.charAt(1)=b,删除b
直到没有重复元素为止,才重新开始计算。
class Solution {
public int lengthOfLongestSubstring(String s) {
//维护当前最长不重复字符子串
Set<Character> set = new HashSet<>();
int left = 0;
int right = 0;
int max = 0;
while(right<s.length()){
if(!set.contains(s.charAt(right))){
//未查到重复字符就一直加,right右移
set.add(s.charAt(right));
right++;
}else{
//right查到重复字符先不动,left右移,set删left经过的字符,直到重复的这个字符删掉为止
set.remove(s.charAt(left));
left++;
}
//每一次计算当前set子串的长度
max = Math.max(max, set.size());
}
return max;
}
}