• 算法——滑动窗口(Sliding Window)


    一、背景知识

    • 滑动窗口算法(Sliding Window)
      • 在给定数组 / 字符串上维护一个固定长度或不定长度的窗口。可以对窗口进行滑动操作、缩放操作,以及维护最优解操作。
      • 题型一:固定长度
      • 题型二:不固定长度

     二、例题

    1、无重复字符的最长子串(不定长度)

    写法一: 我的答案

    1. class Solution {
    2. public int lengthOfLongestSubstring(String s) {
    3. if(s.length()==0){
    4. return 0;
    5. }
    6. int l=0;//左指针
    7. int r=0;//右指针
    8. int maxLen=1;
    9. List list=new ArrayList<>();
    10. while(r
    11. if(!list.contains(s.charAt(r))){
    12. list.add(s.charAt(r));//窗口右侧扩张
    13. maxLen=Math.max(maxLen,r-l+1);//维护一个子串长度的最大值
    14. r++;
    15. }else{
    16. int index=list.indexOf(s.charAt(r));//在窗口里查找被重复的字符的下标
    17. delItems(index,list);//把重复字符及其以前的字符移出窗口
    18. l=l+index+1;//窗口左侧收缩
    19. }
    20. }
    21. return maxLen;
    22. }
    23. //
    24. public void delItems(int end,List list){
    25. while(end>=0){//从后往前删
    26. list.remove(end);
    27. end--;
    28. }
    29. }
    30. }

    写法二: 官方答案

    外循环(for)枚举字符串s的所有字符,当作滑动窗口的左边界,进入内循环(while)后,不断往右移,直到遇到重复的字符后,跳出内循环。

    更新最长子串长度,删除滑动窗口最左边的一个元素。

    如果该元素不是被重复的元素,就不会再次进入内循环,而是一直在外循环徘徊,一个接一个地删掉滑动窗口最左边的元素,直到删掉那个被重复的元素

    1. class Solution {
    2. public int lengthOfLongestSubstring(String s) {
    3. // 哈希集合,记录每个字符是否出现过,相当于滑动窗口
    4. Set occ = new HashSet();
    5. int n = s.length();
    6. // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
    7. int rk = -1, ans = 0;
    8. for (int i = 0; i < n; ++i) {
    9. if (i != 0) {
    10. // 左指针向右移动一格,哈希集合移除一个字符
    11. occ.remove(s.charAt(i - 1));
    12. }
    13. while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
    14. // 不断地移动右指针,哈希集合增加一个字符
    15. occ.add(s.charAt(rk + 1));
    16. ++rk;
    17. }
    18. // 第 i 到 rk 个字符是一个极长的无重复字符子串
    19. // rk-i+1为当前滑动窗口内的子串长度
    20. ans = Math.max(ans, rk - i + 1);
    21. }
    22. return ans;
    23. }
    24. }

    2、找到字符串中所有字母异位词

    该题用排序法会超时,用链表或哈希表会超出内存限制 

    写法一:

    突破点:

    在字符串 s中构造一个长度为与字符串 p的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;当窗口中每种字母的数量与字符串 p中每种字母的数量相同时,则说明当前窗口为字符串 p的异位词。

    1. class Solution {
    2. public List findAnagrams(String s, String p) {
    3. int sLen = s.length(), pLen = p.length();
    4. //当字符串 s 的长度小于字符串 p 的长度时,字符串 s 中一定不存在字符串 p 的异位词
    5. if (sLen < pLen) {
    6. return new ArrayList();
    7. }
    8. List ans = new ArrayList();
    9. int[] sCount = new int[26];//计算字符串s中26个字母出现的个数
    10. int[] pCount = new int[26];//计算字符串p中26个字母出现的个数
    11. for (int i = 0; i < pLen; ++i) {
    12. ++sCount[s.charAt(i) - 'a'];
    13. ++pCount[p.charAt(i) - 'a'];
    14. }
    15. if (Arrays.equals(sCount, pCount)) {//两个数组相等,找到异位词
    16. ans.add(0);//记录初始下标
    17. }
    18. //窗口开始滑动
    19. for (int i = 0; i < sLen - pLen; ++i) {//用滑动窗口遍历字符串s
    20. --sCount[s.charAt(i) - 'a'];//滑动窗口左边界收缩,sCount数组里该字母的个数减1
    21. ++sCount[s.charAt(i + pLen) - 'a'];//滑动窗口右边界扩张,sCount数组里该字母的个数加1
    22. if (Arrays.equals(sCount, pCount)) {//找到异位词
    23. ans.add(i + 1);
    24. }
    25. }
    26. return ans;
    27. }
    28. }

  • 相关阅读:
    Revit SDK 介绍:NewForm 新建体量
    区块链技术与AI:IT领域的未来合作伙伴
    Logstash8.4在Linux系统上的安装以及配置Tomcat日志(ELK安装part2)
    vue.js - 断开发送的请求,解决接口重复请求数据错误问题(vue中axios多次相同请求中断上一个)
    Neural Controlled Differential Equations forIrregular Time Series(NIPS2020)
    layui杂项
    鸿蒙极速入门(六)-加载请求状态管理-LoadState+观察者模式
    Elasticsearch 保姆级入门篇
    适用场景全新升级!扩展 Dragonfly2 作为分布式缓存系统架构 | 龙蜥技术
    设计模式详解:模式汇总与索引清单
  • 原文地址:https://blog.csdn.net/weixin_72052233/article/details/134532303