剑指 Offer 48. 最长不含重复字符的子字符串
思路:hash表+dp 进行更新每一次的最大值
1)遍历字符串
2) 取出当前遍历字符 之前 出现的位置 , 若未出现 则 为-1
3) 状态转移: Hash(j) 存储的是当前字符最近出现的index
f
[
i
]
=
i
−
H
a
s
h
(
j
)
>
f
[
i
−
1
]
?
f
[
i
−
1
]
+
1
:
i
−
H
a
s
h
(
j
)
f[i] = i - Hash(j) > f[i-1] ? f[i-1] + 1 : i - Hash(j)
f[i]=i−Hash(j)>f[i−1]?f[i−1]+1:i−Hash(j)
[^为什么与i-hash(j) 比较]: 通过这个判断当前子串是否在递增,不是的话说明遇到了出现过的字符,此时直接将f[i] 设置为 f[i-1] , 也就是将上次出现过的字符从表中删除,替换为当前的字符。
4) 贪心记录ans
a
n
s
=
m
a
x
(
a
n
s
,
f
[
i
]
)
ans = max(ans,f[i])
ans=max(ans,f[i])
优化:这里可以用滚动数组将f[i-1] 替换
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] idx = new int[130]; // 用Ascii码值存储index 的 map
Arrays.fill(idx , -1);
char[] arr = s.toCharArray();
int ans = 0 ;
int pre = 0 ; // 前一个状态
if(arr.length == 0) return 0;
for(int i = 0; i < arr.length ; i++){
int j = arr[i];
// System.out.println(pre + " " + (i - idx[j]));
pre = i - idx[j] > pre ? pre+1 : i - idx[j]; // 状态转移
ans = Math.max(ans , pre);
idx[j] = i;
}
return ans;
}
}