class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
if (n < 2) return n;
// 队列, 存储最长子字符串
int[] q = new int[n];
int hh = 0, tt = -1;
// 可能不全是小写英文字符, 用map(吐槽一下Java的Map不咋好用)
Map pos = new HashMap();
int max = 0;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
// 查找这个字符上一次出现的位置
int oldP = pos.getOrDefault(c, -1);
// 如果存好的子串包含了上一次出现的s[i], 则s[i]及之前都要舍弃
while (hh <= tt && oldP >= q[hh]) hh++;
// 把当前字符放进字串
q[++tt] = i;
// 更新最大长度
max = Math.max(max, q[tt] - q[hh] + 1);
// 更新s[i]上一次出现的位置
pos.put(c, i);
}
return max;
}
}
更简单的写法
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] last = new int[128];
for(int i = 0; i < 128; i++) last[i] = -1;
int n = s.length(), max = 0, st = 0;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
st = Math.max(st, last[c] + 1);
max = Math.max(max, i - st + 1);
last[c] = i;
}
return max;
}
}
class Solution {
public int lengthOfLongestSubstring(String s) {
List<Character> list = new ArrayList<Character>();
int max = 0;
for (int i = 0; i < s.length(); i++) {
char cur = s.charAt(i);
if (list.contains(cur)) {
while (true) {
Character rc = list.remove(0);
if (rc == cur)
break;
}
}
list.add(cur);
max = list.size() > max ? list.size() : max;
}
return max;
}
}
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int res = 0, tmp = 0;
//当前位置的最大子串长度
for(int i = 0; i < s.length(); i++) {
int index = map.getOrDefault(s.charAt(i), -1);
map.put(s.charAt(i), i);
// 如果当前i位置和重复元素index的距离大于子串长度说明重复字符在子串之外
tmp = tmp < i - index ? tmp + 1 : i - index;
res = Math.max(res, tmp);
}
return res;
}
}
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.length() <= 0){
return 0;
}
Map<Character,Integer> map = new HashMap<>();
map.put(s.charAt(0),0);
int a = 1;
int res = 1;
for(int i = 1;i < s.length();i++){
if(!map.containsKey(s.charAt(i))){
a = a + 1;
}else{
int k = map.get(s.charAt(i));
a = i - k > a ? a+1:i - k;
}
res = Math.max(res,a);
map.put(s.charAt(i),i);
}
return res;
}
}
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() <= 0) {
return 0;
}
Map<Character, Integer> map = new HashMap<>();
int a = 1;
map.put(s.charAt(0), 0);
int res = 1;
for (int i = 1; i < s.length(); i++) {
if (!map.containsKey(s.charAt(i))) {
a += 1;
} else {
int k = map.get(s.charAt(i));
a = i - k <= a ? i - k : a + 1;
}
res = Math.max(res, a);
map.put(s.charAt(i), i);
}
return res;
}
}
/*
①dp[i]:以下标i结尾的不重复子串的长度为dp[i]
②关系式:没有在左侧区间出现过,或者在区间之外:dp[i]=dp[i-1]+1
左侧区间出现过:dp[i]=i-k(字符上一次出现位置)
哈希表字符和下标的映射
*/
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.length() <= 0) return 0;
int len = s.length();
Map<Character,Integer> map = new HashMap<>();
int[] dp = new int[len];
dp[0] = 1;
map.put(s.charAt(0),0);
int res = 1;
for(int i = 1;i < len;i++){
if(!map.containsKey(s.charAt(i))){
dp[i] = dp[i - 1] + 1;
}else{
int k = map.get(s.charAt(i));
//i-k<=dp[i-1]说明在重复字符串范围内,需要更新长度
//否则在范围外,可以使用dp[i-1]
dp[i] = i - k <= dp[i - 1] ? i - k : dp[i - 1] + 1;
}
res = Math.max(res,dp[i]);
map.put(s.charAt(i),i);
}
return res;
}
}
优化后
空间复杂度O(1)
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.length() <= 0) return 0;
int len = s.length();
Map<Character,Integer> map = new HashMap<>();
//优化=> 单个变量
int dp = 1;
map.put(s.charAt(0),0);
int res = 1;
for(int i = 1;i < len;i++){
if(!map.containsKey(s.charAt(i))){
dp = dp + 1;
}else{
int k = map.get(s.charAt(i));
//i-k<=dp[i-1]说明在重复字符串范围内,需要更新长度
//否则在范围外,可以使用dp[i-1]
dp = i - k <= dp ? i - k : dp + 1;
}
res = Math.max(res,dp);
map.put(s.charAt(i),i);
}
return res;
}
}class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.length() <= 0) return 0;
int len = s.length();
Map<Character,Integer> map = new HashMap<>();
//优化=> 单个变量
int dp = 1;
map.put(s.charAt(0),0);
int res = 1;
for(int i = 1;i < len;i++){
if(!map.containsKey(s.charAt(i))){
dp = dp + 1;
}else{
int k = map.get(s.charAt(i));
//i-k<=dp[i-1]说明在重复字符串范围内,需要更新长度
//否则在范围外,可以使用dp[i-1]
dp = i - k <= dp ? i - k : dp + 1;
}
res = Math.max(res,dp);
map.put(s.charAt(i),i);
}
return res;
}
}
共以下 12 个回答
containsKey而不是contains
双指针
更简单的写法
时间复杂度:O(N)
空间复杂度:O(1)
思路:从第一个元素开始向左遍历,每遍历一个元素用就把它加入list,如果list已有这个元素(假设这个元素是a),就对list里的元素进行删除,删除的元素为从第一个元素开始直到删除a位置,然后在对剩余元素的list的个数进行判断,看它是否大于max.
时间空间复杂度为O(n)
时间:O(n),空间:O(n)
空间复杂度O(N)时间复杂度O(N)
优化后
空间复杂度O(1)