//给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
// 示例 1:
//输入: s = “abcabcbb”
//输出: 3
//解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
//
// 示例 2:
//输入: s = “bbbbb”
//输出: 1
//解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
//
/// 示例 3:
//输入: s = “pwwkew”
//输出: 3
//解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
// 请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
//
// 示例 4:
//输入: s = “”
//输出: 0
//
// 提示:
// 0 <= s.length <= 5 * 104
// s 由英文字母、数字、符号和空格组成
public class Test4 {
public static void main(String[] args) {
String str = "sadeabcd";
int i = lengthOfLongestSubstring(str);
System.out.println(i);
}
public static int lengthOfLongestSubstring(String s) {
// 开始索引
int start = 0;
// 上一次重复字符的索引
int pre = 0;
// 无重复字符的长度
int len = 0;
// 最大无重复字符的长度
int maxLen = 0;
// 用Map存字符和索引
HashMap<Character, Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if( !map.containsKey(s.charAt(i))){
//map中没有这个字符,长度+1
len++;
//将新字符保存在map中
map.put(s.charAt(i),i);
if( maxLen < len){
maxLen = len;
}
}else{
// 获得前一个相同字符的索引
pre = map.get(s.charAt(i));
// 删除前一个相同字符之前的数值(包括前一个字符)
for (int j = start; j <= pre; j++) {
map.remove(s.charAt(j));
}
//更新当前索引
map.put(s.charAt(i),i);
//长度为当前索引 - pre
len = i - pre;
//开始索引为 pre + 1
start = pre + 1;
}
}
return maxLen;
}
}
注意:
当遇到相同字符的时候,前一个字符之前的值都将无效化。
比如 sabca , s是无效的,
因为a重复了,即使后面再遇到 s ,也会因为 a 重复而无效
动态规划解题
public class LongestSubString {
public static void main(String[] args) {
String str = "abcabcbb";
int num = lengthOfLongestSubstring(str);
System.out.println(num);
}
public static int lengthOfLongestSubstring(String str){
if(str.length() == 0){
return 0;
}
int[] dp = new int[str.length()];
dp[0] = 1;
int len = 1;
for (int i = 1; i < dp.length; i++) {
char c = str.charAt(i);
if(str.contains(c + "")){
int lastIndex = str.lastIndexOf(c, i - 1);
int d = i - lastIndex;
if(d <= dp[i-1]){
dp[i] = d;
}else {
dp[i] = dp[i-1] + 1;
}
} else {
dp[i] = dp[i-1] + 1;
}
len = Math.max(len,dp[i]);
}
return len;
}
}