巩固练习长度最小的子数组-904/76

904.水果成篮

解题思路

简而言之,是为了找最长连续两个数的序列。
前面的理解了,自己上手又有点不行。自己写的↓,感觉思路是对的,却不行。(发现for循环初始化搞错了)

/**
* @param {number[]} fruits
* @return {number}
*/
var totalFruit = function(fruits) {
   let i = 0
   let flag = []
   let typeF = 0
   let maxLen = 0
   for(let j=fruits.length;j<fruits.length;j++){
       flag.push(fruits[j])
       if(!flag.includes(fruits[j])){ //如果篮子里没有这种水果则加入这种水果
           // flag.push(fruits[j])
           typeF++
       }
       if(typeF > 2){ //如果篮子里水果种类 > 2
           maxLen = Math.max(maxLen,j-i+1) //获取当前的序列长度
           //删除一种水果
           deletedF = flag.shift()//确定删除的这种水果
           i = flag.lastIndexOf(deleteF) != -1 ?  flag.lastIndexOf(deleteF) : i+1 //找到这种水果最后出现的位置,变更i的位置
           flag = flag.slice(i-1)//删除i之前的
           typeF--
       }
       
   }
   return flag.length
};

改正之后是

var totalFruit = function(fruits) {
   let i = 0
   let flag = []
   let typeF = 0
   let maxLen = 0
   for(let j=0;j<fruits.length;j++){
//        if(flag.lastIndexOf(fruits[j]) == -1){ //如果篮子里没有这种水果则加入这种水果
//        typeF++
//    } 这样也可以
       if(!flag.includes(fruits[j])){ //如果篮子里没有这种水果则加入这种水果
           typeF++
       }
        flag.push(fruits[j])
        // typeF = Array.from(new Set(flag)).length //获取现在的水果种类数
    //    console.log(typeF)
       if(typeF > 2){ //如果篮子里水果种类 > 2
           //删除一种水果
        //    deletedF = flag.shift()//确定删除的这种水果
        //    i = flag.lastIndexOf(deleteF) != -1 ?  flag.lastIndexOf(deleteF) : i+1 //找到这种水果最后出现的位置,变更i的位置
        //    flag = flag.slice(i-1)//删除i之前的
        //    typeF--
            flag.shift() //删除最前面的
            i++ //变更i的位置
            typeF = Array.from(new Set(flag)).length //获取现在的水果种类数
       }
       maxLen = Math.max(maxLen,j-i+1) //获取当前的序列长度
       
   }
   return flag.length
   //return maxLen 也可以
};

去看了别人的题解,是最大滑窗和最小话长的区别,感觉总结的很好:

  • 最小滑窗模板:给定数组 nums,定义滑窗的左右边界 i, j,求满足某个条件的滑窗的最小长度。
while j < len(nums):
    判断[i, j]是否满足条件
    while 满足条件:
        不断更新结果(注意在while内更新!)
        i += 1 (最大程度的压缩i,使得滑窗尽可能的小)
    j += 1

//作者:frostep
//链接:https://leetcode.cn/problems/fruit-into-baskets/solution/shen-du-jie-xi-zhe-dao-ti-he-by-linzeyin-6crr/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 最大滑窗模板:给定数组 nums,定义滑窗的左右边界 i, j,求满足某个条件的滑窗的最大长度。
while j < len(nums):
    判断[i, j]是否满足条件
    while 不满足条件:
        i += 1 (最保守的压缩i,一旦满足条件了就退出压缩i的过程,使得滑窗尽可能的大)
    不断更新结果(注意在while外更新!)
    j += 1

//作者:frostep
//链接:https://leetcode.cn/problems/fruit-into-baskets/solution/shen-du-jie-xi-zhe-dao-ti-he-by-linzeyin-6crr/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

JavaScript解法代码

var totalFruit = function(fruits) {
    let i = 0
    const blanket = new Map()
    let maxLen = 0
    for(let j=0;j<fruits.length;j++){
        blanket.set(fruits[j], (blanket.get(fruits[j]) || 0) + 1)
        while(blanket.size > 2){
            blanket.set(fruits[i], blanket.get(fruits[i]) - 1);
            if (blanket.get(fruits[i]) == 0) {
                blanket.delete(fruits[i]);
            }
            ++i;
        }
        maxLen = Math.max(maxLen, j-i+1)
    }
    return maxLen
};

Python解法代码

自己的

虽然可以AC,但其实是有问题的。

class Solution(object):
    def totalFruit(self, fruits):
        """
        :type fruits: List[int]
        :rtype: int
        """
        fruitsType = 0
        blanket = []
        for j in range(len(fruits)):
            if(fruits[j] not in blanket):
                fruitsType+=1
            blanket.append(fruits[j])

            if(fruitsType > 2):
                del(blanket[0])
                fruitsType = len(list(set(blanket)))
        return len(blanket)

滑动窗口

class Solution(object):
    def totalFruit(self, fruits):
        """
        :type fruits: List[int]
        :rtype: int
        """
        blanket = {}
        maxLen = 0
        i = 0
        for j in range(len(fruits)):
            count =( blanket.get(fruits[j]) or 0)+1
            blanket[fruits[j]] = count

            while(len(blanket) > 2):
                count = blanket.get(fruits[i])-1
                blanket[fruits[i]] = count
                
                if (blanket[fruits[i]] == 0):
                    del blanket[fruits[i]]
                i+=1
            maxLen = max(maxLen,j-i+1)
        return maxLen

76.最小覆盖子串

解题思路

用滑动窗口找最短的字符串。

出现的问题

没有对对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量这个限制条件作出处理,所以对于如"aa","aa"这中例子处理不了。

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function(s, t) {
    let i = 0
    let substr = ''
    let allExist
    let minLen = Number.MAX_VALUE
    let minstr =''
    for(let j=0;j<s.length;j++){
        substr += s[j]
        
        //判断条件 substr是否包含了t内的每个字符
        allExist= [...t].every(char => substr.includes(char));
        while(allExist){
            temp = minLen
            minLen = Math.min(minLen,j-i+1)
            if(minLen < temp){ //字符串改变了,变短了,则存储此时的字符串
                minstr = substr
                console.log(minstr)
            }

            substr = substr.substr(1) //删除第一个字符
            allExist= [...t].every(char => substr.includes(char)); //判断allExist 是否仍满足条件
            i++            
            
        }
    }
    if(t.length < minstr.length){
        return ""
    }
    else{
        return minstr
    }
    
};

使用Map解决了上述的问题,但是提交的时候因为有个例子非常长,所以超出了时间限制。

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function(s, t) {
    let tDict = new Map();
    [...t].forEach(element => {
        tDict.set(element, (tDict.get(element) || 0) + 1)
    })
    let i = 0;
    let substr = '';
    let substrDict = new Map();
    let allExist;
    let minLen = Number.MAX_VALUE;
    let minstr ='';
    for(let j=0;j<s.length;j++){
        substr += s[j]
        substrDict.set(s[j],(substrDict.get(s[j]) || 0)+1)
        //判断条件 substr是否包含了t内的每个字符
        // allExist= [...t].every(char =>  [...substrDict.keys()].join('').includes(char));
        allExist= [...t].every(char => substr.includes(char));

        [...t].forEach(element => {
            if(substrDict.get(element) < tDict.get(element)){ //如果少于,则allExist = false
                allExist = false
            }
        })
        
        while(allExist){
            temp = minLen
            minLen = Math.min(minLen,j-i+1)
            if(minLen < temp){ //字符串改变了,变短了,则存储此时的字符串
                // minstr = [...substrDict.keys()].join('')
                minstr = substr
                console.log('minstr:',minstr)
            }
            //删除第一个字符
            substr = substr.substr(1) 
            substrDict.set(s[i],substrDict.get(s[i])-1)
            if (substrDict.get(s[i]) == 0) {
                substrDict.delete(s[i]);
            }
            allExist= [...t].every(char => substr.includes(char));
            //"对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。"
            //判断t中字符的长度 与 substr比较
            [...t].forEach(element => {
                if(substrDict.get(element) < tDict.get(element)){ //如果少于,则allExist = false
                    allExist = false
                }
            }) 
            i++        
               
        }
    }
    return minstr
};

看了答案,还没参悟。
ta也是用Map,但是对map的size有更灵活的运用。

JavaScript解法代码


/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function (s, t) {
    const target = new Map();
    let minChar;
    let nowChar = "";
    [...t].forEach(element => {
    target.set(element, (target.get(element) || 0) + 1)
})
    let size = target.size
    let  i= 0
    for (let j=0; j < s.length; j++) {
        if (target.has(s[j])) target.set(s[j], target.get(s[j]) - 1);
        if (target.get(s[j]) === 0) size--
        // console.log('size: ',size, !size)

        while (!size) {
            nowChar = s.substring(i, j + 1);
            // console.log('nowChar: ',nowChar)
            if (target.has(s[i])) {
                target.set(s[i], target.get(s[i]) + 1)
                if (target.get(s[i]) === 1) {
                    size++
                    console.log(!minChar || minChar.length > nowChar.length)
                    if (!minChar || minChar.length > nowChar.length) minChar = nowChar; //!minChar 判断minChar不为空(不为初始值)
                    // console.log(minChar)
                 }
             }
             i++;
         }
     }
     return minChar ? minChar : '';
};

Python解法代码

//待完成

总结:

  1. map集合的操作要注意:包括set、get、has的运用
    target.set(element, (target.get(element) || 0) + 1)
  2. 滑动窗口通用解总结:
    • 最小滑窗模板:给定数组 nums,定义滑窗的左右边界 i, j,求满足某个条件的滑窗的最小长度。
while j < len(nums):
    判断[i, j]是否满足条件
    while 满足条件:
        不断更新结果(注意在while内更新!)
        i += 1 (最大程度的压缩i,使得滑窗尽可能的小)
    j += 1

//作者:frostep
//链接:https://leetcode.cn/problems/fruit-into-baskets/solution/shen-du-jie-xi-zhe-dao-ti-he-by-linzeyin-6crr/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 最大滑窗模板:给定数组 nums,定义滑窗的左右边界 i, j,求满足某个条件的滑窗的最大长度。
while j < len(nums):
    判断[i, j]是否满足条件
    while 不满足条件:
        i += 1 (最保守的压缩i,一旦满足条件了就退出压缩i的过程,使得滑窗尽可能的大)
    不断更新结果(注意在while外更新!)
    j += 1

//作者:frostep
//链接:https://leetcode.cn/problems/fruit-into-baskets/solution/shen-du-jie-xi-zhe-dao-ti-he-by-linzeyin-6crr/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容