Github IO

每日一题——分治,滑窗

力扣395

https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/

  1. 至少有K个重复字符的最长子串
    给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。

滑动窗口

滑动窗口适合的问题类型

这题用滑动窗口并不是太好。滑动窗口适合的问题是用一个窗口维护窗口内子串的属性,右边界++导致属性增加,左边界--导致属性减小,属性不能超过/低于某值,而要获得的是最长的窗口。这样滑动窗口就为每个r找到了唯一的最优l。
找到一个适合的窗口后,再探寻下一个r的l,l只能往前移动,也就是说所有l之前的值都无意义,这样就实现了剪枝(?)的目的

不满足条件的字符种类数less无法用滑动窗口维护

分析本题,对于每一个r,r前面的每一个l都可能有意义,因为可能r++导致的条件不满足(less++)需要l++来消除(less--),中间去掉了很多合理的字符。而下一次r++时,可能被去掉的一部分加上r现在的位置的值就满足了,也就是说在l现在的位置之前出现了更优的合理值。所以less无法用滑动窗口维护。

引入新属性字符种类数tot用滑动窗口维护

  • tot用滑窗维护:tot只有在左边界向前时减小,右边界向前时增大,满足约束被r++破坏时l只能++的条件,可以用滑窗。
  • tot相当于约束条件:tot=t是约束条件,若tott且窗口最大时没有less0,那必然没有更小的窗口同时满足tott且less0。
  • 遍历tot,记录less。

更快的方法:分治+递归

  • 将整个数组当作第一级窗口,每次统计窗口内字符出现次数,剔除掉一个不符合条件的字符,选出各个符合条件的窗口
  • 对这些窗口再次调用,直到没有不符合条件的字符出现。
posted @ 2021-02-27 14:18  laiyk  阅读(76)  评论(0)    收藏  举报