题目:给定一个字符串 s
,请你找出其中不含有重复字符的最长子串的长度。
最初设想:
i=0,j=1,模板str为第一个字符;
j一路和str比下去,不一样就把当前字符加到str里,
一样就先更新一下str的长度size,再i++,j=i+1,str为当前i的字符,继续比下去。代码如下
var lengthOfLongestSubstring = function(s) {
if(s.length===0) return 0 //长度为零返回0
let i=0,j=1,size=1
let str=s[i]
while(j<s.length){
if(str.indexOf(s[j])===-1){ //当前字符不重复
str+=s[j] //当前字符加入模板
j++
}else{ //重复
if(size<j-i){ //更新size更大
size=j-i
}
i++
j=i+1
str=s[i] //初始化模板
}
}
size=size>=str.length?size:str.length //防止全程未重复,size没更新过
return size
};
但其实在遇到重复,i重置时,i++是低效且没必要的,可以直接从模板中重复的那个字符的下一位开始,继续比较,同时要把indexOf放在判断外面使其返回值在后面用得到
var lengthOfLongestSubstring = function(s) {
if(s.length===0) return 0
let i=0,j=1,size=1
let str=s[i]
while(j<s.length){
let index=str.indexOf(s[j]) // s[j]在模板里的重复字符所处位置
if(index===-1){
str+=s[j]
j++
}else{
if(size<j-i){
size=j-i
}
i=i+index+1 //从重复字符后面开始
j=i+1
str=s[i]
}
}
size=size>=str.length?size:str.length
return size
};
关于size的判断和更新还可以简化:在每次增加新字符之后更新size,兼顾了全程无重复的情况:
var lengthOfLongestSubstring = function(s) {
if(s.length===0) return 0
let i=0,j=1,size=1
let str=s[i]
while(j<s.length){
let index=str.indexOf(s[j])
if(index===-1){
str+=s[j]
j++
size=size>=str.length?size:str.length //每增加一个字符更新一次size
}else{
i=i+index+1
j=i+1
str=s[i]
}
}
return size
};
其实整个题目无非是遇到重复的怎么样,没有重复又怎么样,难点在于如何获取到最大长度:在某一个关键节点更新size,即与当前模板长度比较。