题外话:
决定把算法捡起来,没想到leetcode国际服居然上不去了,这垃圾宽带。只能转战国服了。
初步解题思路:
遍历入参s,并维护一个map,key为s[i],value为i。
为什么需要这个map呢?当然是为了便于后面查找哪个字符跟当前坐标的字符重复了,如果重复了,假设map.get(当前字符)=dupIndex,下次搜索区间应该从leftIndex = dupIndex+1开始。
这样我们保证了搜索区间里的数据是不重复的。所以不用担心map被覆盖的问题,因为太早的重复数据已经没意义了(这一句看不懂可以忽略,我也不知道我在讲什么)。
但是map拿出的数据一定有效吗?最初我没有仔细思考,反正我维护了一个有效搜索区间,只要map.get(当前字符)>leftIndex即可。后面仔细想了下,回文数可以作为反例。
=======================分割================================
下图表示了两个字符重复的情况。把preIndex+1即可
talk is cheap:
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.length() == 0) {
return 0;
}
int leftIndex = 0;
int rightIndex = 0;
Map<Character,Integer> map = new HashMap<>();
int resultLen = 0;
char[] sArr = s.toCharArray();
for(int i=0;i<sArr.length;i++) {
char c = sArr[i];
// 与s[i] 相同字符的 上个坐标
Integer dupIndex = map.get(c);
if(dupIndex != null && dupIndex >= leftIndex) {
resultLen = Math.max(i-leftIndex,resultLen);
// 下次搜索区间的起始坐标
leftIndex = dupIndex+1;
}
map.put(c,i);
}
return Math.max(s.length()-leftIndex,resultLen);
}
}
但是这个代码只击败了50%+的人。emmm,我不服,想了想思路应该优化不了,那么数据结构可能有问题。于是把hashMap换作数组即可。
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.length() == 0) {
return 0;
}
int leftIndex = 0;
//Map<Integer,Integer> map = new HashMap<>();
int[] map = new int[128];
for(int i=0; i<128; i++) {
map[i] = -1;
}
int resultLen = 0;
char[] sArr = s.toCharArray();
for(int i=0;i<sArr.length;i++) {
char c = sArr[i];
// 与s[i] 相同字符的 上个坐标
int dupIndex = map[c];
if(dupIndex != -1 && dupIndex >= leftIndex) {
resultLen = Math.max(i-leftIndex,resultLen);
// 下次搜索区间的起始坐标
leftIndex = dupIndex+1;
}
//map.put(c,i);
map[c] = i;
}
return Math.max(s.length()-leftIndex,resultLen);
}
}