Open RubyLouvre opened 5 years ago
var minWindow = function(s, t) {
var hash = {}
for(var i = 0; i < t.length; i++){
hash[t[i]] = 0;
}
var ret = ''
var left = 0, right = 0
while(right < s.length){
var match = false
if(s[right] in hash){
console.log("命中",s[right])
match = true
for(var r in hash){
if(!hash[r]){
match = false
}
}
}
if(match){
while(!(s[left] in hash)){
left++
}
if(!ret ||ret.length > s.slice(left, right+1)){
ret = s.slice(left, right+1)
}
right++
// console.log(s.slice(left, right+1), Object.assign({}, hash))
//break
}else{
if(right - left < t.length){ // 如果长度不够
right++ //向右移动
if(hash[s[right]] >= 0){
hash[s[right]]++
}
}else{ //长度够了,但没有命中,
if( hash[s[left]] > 0){
hash[s[left]]--
}
console.log("left向前")
left++
}
}
}
return ret;
};
3. Longest Substring Without Repeating Characters
找到字符串不出现重复字符的最长子串的长度。
滑动窗口法
滑动窗口法的优化
我们从左到右遍历,用hash大法记录每个字符第一次出现的位置,记录这个不断变长的子串的长度,默认它就是最大的。当我们遇到一个重复字符出现 在hash中,我们需要退回这个字符上次的出现的位置的后一位,然后获取这个字符到重复字符的子串,比如它们的大小。
这说得有点抽象,看一下字符串abcdaefghbkji123, 我们第一个子串是abcd, 再前进就碰到a,因此需要改到上一个a的位置的后面,重新截取一个子串,得到bcdae时,长度就大于abcd,然后就是不断增大这个子串。
但怎么增大呢,我们可以通过记录一个left变量,及一个不断往后走的right变量,就可以得到
s.slice(left, right+1)
子串。下面是答案, 我们把每次碰到重复字符串,得到的子串也显示出来了。
该算法的时间复杂度为O(n),空间复杂度为O(1)
159. Longest Substring with At Most Two Distinct Characters
求一个包括最多2种字母的最长子串
我们需要一个hash记录每个字符出现的次数,当字符的数量超过两个,那么需要移动left,将left所指向的那种字符全部删掉。
另一种解法,不使用哈希
340. Longest Substring with At Most K Distinct Characters.
求一个包括最多K种字母的最长子串
395. Longest Substring with At Least K Repeating Characters
要求是找出最长的子串,子串中的每一个字符都要重复至少k次。
这是一个经典的分治法解决的问题,关键在于我们如何将这个问题分解为更小的子问题。反过来想,这个子字符串一定不包含什么元素呢?当一个元素出现的总次数小于k,那么该元素一定不在子字符串中,只需要将其作为分界点,分别找出左半部分和右半部分的满足条件的最长子字符串。