算法-滑动窗口类型

6666

滑动窗口

1、大小为K的最大和子数组

给定一个数组,找出该数组中所有大小为“K”的连续子数组的平均值。

让我们用实际输入来理解这个问题:

Array: [1, 3, 2, 6, -1, 4, 1, 8, 2], K=5

1、对于前5个数字(索引0-4的子数组),平均值为:(1 + 3 + 2 + 6−1)/ 5 = > 2.2
2、对于前5个数字(索引1-5的子数组),平均值为:(3 + 2 + 6-1 + 4) / 5 = > 2. 8
....

Output: [2.2, 2.8, 2.4, 3.6, 2.8]

按照蛮力算法,时间复杂度O(N*K)


  public static double[] findAverages(int k, int[] arr) {
      double[] result = new double[arr.length - k + 1];
      for (int i = 0; i <= arr.length - k; i++) {
          double sum = 0;
          for (int j = i; j < i + k; j++) {
              sum += arr[j];
          }
          result[i] = sum / k;
      }
      return result;
  }

滑动窗口,时间复杂度O(N)

该图中,我们的窗子不断往右一格一个移动


public static double[] findAveragesV1(int k, int[] arr) {
    double[] result = new double[arr.length - k + 1];
    double windowSum = 0;
    int windowStart = 0;
    for (int windowEnd = 0; windowEnd < arr.length; windowEnd++) {
        windowSum += arr[windowEnd];
        if (windowEnd >= k - 1) {
            result[windowStart] = windowSum / k;
            windowSum -= arr[windowStart];
            windowStart++;
        }
    }
    return result;
}

2、给定和的最小子数组

给定一个正数数组和一个正数’ S ‘,求和大于等于’ S '的最小连续子数组的长度。如果不存在子数组,则返回0。

Input: [2, 1, 5, 2, 3, 2], S=7 
Output: 2
Explanation: The smallest subarray with a sum great than or equal to '7' is [5, 2].

这个问题遵循滑动窗口模式,我们可以使用类似于在大小k的最大和子数组中讨论的策略。但有一个区别:在这个问题中,滑动窗口的大小不是固定的。我们将如何解决这个问题:

  • 首先,我们将从数组开始的元素相加,直到它们的总和大于或等于’ S '。
  • 这些元素将构成我们的滑动窗口。我们被要求找到总和大于或等于S的最小窗口。我们将这个窗口的长度记为到目前为止最小的窗口。
  • 在此之后,我们将继续在滑动窗口中添加一个元素(即向前滑动窗口),以逐步的方式。
  • 在每一步中,我们也会尝试从一开始就缩小窗口。我们将缩小窗口,直到窗口的和再次小于’ S '。这是需要的,因为我们打算找到最小的窗口。这种收缩也将分多个步骤进行;在每一步中,我们将做两件事:
    1、检查当前窗口长度是否为迄今为止最小的,如果是,则记住其长度。
    2、从运行和中减去窗口的第一个元素以缩小滑动窗口。


public static int findMinSubArray(int s, int[] arr) {
    int windowSum = 0, minLength = Integer.MAX_VALUE;
    int windowStart = 0;
    for (int windowEnd = 0; windowEnd < arr.length; windowEnd++) {
        windowSum += arr[windowEnd];
        while (windowSum >= s) {
            minLength = Math.min(minLength, windowEnd - windowStart + 1);
            windowSum -= arr[windowStart];
            windowStart++;
        }
    }
    return minLength == Integer.MAX_VALUE ? 0 : minLength;
}

上述算法的时间复杂度为O(N)。外部for循环运行所有元素,而内部while循环只处理每个元素一次,因此算法的时间复杂度为O(N+N)渐近等价于O (N)。

3、具有K个不同字符的最长子串

给定一个字符串,找出其中最长的子字符串的长度,且不超过K个不同的字符。

Input: String="araaci", K=2
Output: 4
Explanation: The longest substring with no more than '2' distinct characters is "araa".

这个问题遵循滑动窗口模式,我们可以使用与给定和的最小子数组中讨论的类似的动态滑动窗口策略。我们可以使用HashMap来记住我们处理过的每个字符的频率。我们将如何解决这个问题:

  • 首先,我们将从字符串的开头插入字符,直到HashMap中有“K”个不同的字符。
  • 这些字符将构成我们的滑动窗口。我们被要求找到不超过“K”个不同字符的最长窗口。我们将把这个窗口的长度记为迄今为止最长的窗口。
  • 在此之后,我们将继续在滑动窗口中添加一个字符(即向前滑动窗口),以逐步的方式。
  • 在每一步中,如果HashMap中不同字符的计数大于“K”,我们将尝试从一开始就缩小窗口。我们将缩小窗口,直到HashMap中的不同字符不超过“K”个。这是需要的,因为我们打算找到最长的窗口。
  • 在收缩时,我们将减少字符走出窗口的频率,并在其频率变为零时将其从HashMap中删除。
  • 在每一步结束时,我们将检查当前窗口的长度是否是到目前为止最长的,如果是,则记住它的长度。

public static int findLength(String str, int k) {
    if (str == null || str.length() == 0 || str.length() < k) {
        throw new IllegalArgumentException();
    }
    int windowStart = 0, maxLength = 0;
    Map<Character, Integer> charFrequencyMap = new HashMap<>();
    for (int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
        char rightChar = str.charAt(windowEnd);
        charFrequencyMap.put(rightChar, charFrequencyMap.getOrDefault(rightChar, 0) + 1);
        while (charFrequencyMap.size() > k) {
            char leftChar = str.charAt(windowStart);
            charFrequencyMap.put(leftChar, charFrequencyMap.get(leftChar) - 1);
            if (charFrequencyMap.get(leftChar) == 0) {
                charFrequencyMap.remove(leftChar);
            }
            windowStart++;
        }
        maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
    }
    return maxLength;

}


上述算法的时间复杂度为O(N),其中’ N '是输入字符串中的字符数。外部的for循环运行所有字符,而内部的while循环只处理每个字符一次,因此算法的时间复杂度将为O(N+N)渐近等价于O (N)。

4、篮子里的水果

给定一个字符数组,其中每个字符代表一棵果树,给你两个篮子,你的目标是在每个篮子里放入最大数量的水果。唯一的限制是每个篮子只能放一种水果。 你可以从任何一棵树开始,但是一旦你开始了,你就不能跳过一棵树。你会从每棵树上摘一个水果,直到你摘不动为止,也就是说,当你不得不摘第三种水果时,你会停下来。 编写一个函数返回两个篮子中水果的最大数量。

Input: Fruit=['A', 'B', 'C', 'A', 'C']
Output: 3
Explanation: We can put 2 'C' in one basket and one 'A' in the other from the subarray ['C', 'A', 'C']

这个问题遵循滑动窗口模式,非常类似于具有K个不同字符的最长子字符串。在这个问题中,我们需要找到不超过两个不同字符(或水果类型!)的最长子数组的长度。这将当前问题转换为具有K个不同字符的最长子串,其中K=2。


public static int findLength(char[] arr) {
      int windowStart = 0, maxLength = 0;
      Map<Character, Integer> fruitFrequencyMap = new HashMap<>();
      for (int windowEnd = 0; windowEnd < arr.length; windowEnd++) {
          fruitFrequencyMap.put(arr[windowEnd], fruitFrequencyMap.getOrDefault(arr[windowEnd], 0) + 1);
          while (fruitFrequencyMap.size() > 2) {
              fruitFrequencyMap.put(arr[windowStart], fruitFrequencyMap.get(arr[windowStart]) - 1);
              if (fruitFrequencyMap.get(arr[windowStart]) == 0) {
                  fruitFrequencyMap.remove(arr[windowStart]);
              }
              windowStart++;
          }
          maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
      }
      return maxLength;
  }

5、不重复的子串

给定一个字符串,找出不包含重复字符的最长子字符串的长度。

Input: String="aabccbb"
Output: 3
Explanation: The longest substring without any repeating characters is "abc".

这个问题遵循滑动窗口模式,我们可以使用与K个不同字符的最长子串中讨论的类似的动态滑动窗口策略。我们可以使用HashMap来记住我们处理过的每个字符的最后一个索引。每当我们得到一个重复的字符,我们将收缩滑动窗口,以确保我们总是有不同的字符在滑动窗口。

public static int findLength(String str) {
    int windowStart = 0, maxLength = 0;
    Map<Character, Integer> charIndexMap = new HashMap<>();
    for (int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
        char rightChar = str.charAt(windowEnd);
        if (charIndexMap.containsKey(rightChar)) {
            windowStart = Math.max(windowStart, charIndexMap.get(rightChar) + 1);
        }
        charIndexMap.put(rightChar, windowEnd);
        maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
    }
    return maxLength;
}

上述算法的时间复杂度为O(N),其中’ N '是输入字符串中的字符数。

6、替换后具有相同字母的最长子串

给定一个只有小写字母的字符串,如果你被允许用任何字母替换不超过’ k '个字母,找出替换后具有相同字母的最长子字符串的长度。

Input: String="aabccbb", k=2
Output: 5
Explanation: Replace the two 'c' with 'b' to have a longest repeating substring "bbbbb".

这个问题遵循滑动窗口模式,我们可以使用与No-repeat Substring中讨论的类似的动态滑动窗口策略。我们可以使用HashMap来计算每个字母出现的频率。 我们将遍历字符串,在窗口中每次添加一个字母。我们还将跟踪任何窗口中最大重复字母的计数(我们将其称为maxRepeatLetterCount)。所以在任何时候,我们知道我们可以有一个窗口,其中有一个字母重复maxRepeatLetterCount次,这意味着我们应该尝试替换剩余的字母。如果我们有超过k个剩余字母,我们应该缩小窗口,因为我们不允许替换超过k个字母。


public static int findLength(String str, int k) {
    int windowStart = 0, maxLength = 0, maxRepeatLetterCount = 0;
    Map<Character, Integer> letterFrequencyMap = new HashMap<>();
    for (int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
        char rightChar = str.charAt(windowEnd);
        letterFrequencyMap.put(rightChar, letterFrequencyMap.getOrDefault(rightChar, 0) + 1);
        maxRepeatLetterCount = Math.max(maxRepeatLetterCount, letterFrequencyMap.get(rightChar));

        if (windowEnd - windowStart + 1 - maxRepeatLetterCount > k) {
            char leftChar = str.charAt(windowStart);
            letterFrequencyMap.put(leftChar, letterFrequencyMap.get(leftChar) - 1);
            windowStart++;
        }
        maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
    }
    return maxLength;
}


上述算法的时间复杂度为O(N),其中’ N '是输入字符串中的字母数。

7、替换后带有1的最长子数组

给定一个包含0和1的数组,如果你被允许用1替换不超过k个0,找出全部为1的最长连续子数组的长度。

Input: Array=[0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1], k=2
Output: 6
Explanation: Replace the '0' at index 5 and 8 to have the longest contiguous subarray of 1s having length 6.

这个问题遵循滑动窗口模式,非常类似于替换后具有相同字母的最长子字符串。唯一的区别是,在这个问题中,我们在输入数组中只有两个字符(1和0)。 按照类似的方法,我们将遍历数组,每次在窗口中添加一个数字。我们还将跟踪当前窗口中重复1的最大数量(我们将其称为maxOnesCount)。所以在任何时候,我们知道我们可以有一个有15个重复maxOnesCount时间的窗口,所以我们应该尝试替换剩下的0。如果我们有超过k个剩余的0,我们应该缩小窗口,因为我们不允许替换超过k个0。

public static int findLength(int[] arr, int k) {
    int windowStart = 0, maxLength = 0, maxOnesCount = 0;
    for (int windowEnd = 0; windowEnd < arr.length; windowEnd++) {
        if (arr[windowEnd] == 1) {
            maxOnesCount++;
        }

        if (windowEnd - windowStart + 1 - maxOnesCount > k) {
            if (arr[windowStart] == 1) {
                maxOnesCount--;
            }
            windowStart++;
        }
        maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
    }
    return maxLength;
}

上述算法的时间复杂度为 O(N),其中’ N '是输入数组中数字的计数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/259255.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

贝蒂快扫雷~(C语言)

✨✨欢迎大家来到贝蒂大讲堂✨✨ ​​​​&#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;贝蒂的游戏 贝蒂的主页&#xff1a;Betty‘s blog 引言&#xff1a; 扫雷相信大家小时候到玩过吧&#xff0c;那…

Gin之GORM多表关联查询(多对多;自定义预加载SQL)

数据库三个,如下: 注意:配置中间表的时候,表设计层面最好和配置的其他两张表契合,例如其他两张表为fate内的master和slave;要整合其对应关系的话,设计中间表的结构为master_id和slave_id最好(不然会涉及重写外键的操作) 重写外键(介绍) 对于 many2many 关系,连接表…

DBdoctor,致力于解决数据库的一切性能问题

17(一起)&#xff0c;这是我的幸运数字&#xff0c;恰巧今年8月17日在DTCC大会上我们全网首次发布DBdoctor&#xff0c;今天同样是17日&#xff0c;在全网首发整四个月后我们发布重磅大版本V3.1。值此重大更新之际&#xff0c;想与各有识之士深度聊一下这款产品&#xff0c;以及…

【LeetCode刷题】--244.最短单词距离II

244.最短单词距离II 方法&#xff1a;哈希表双指针 class WordDistance {HashMap<String,List<Integer>> map new HashMap<>();public WordDistance(String[] wordsDict) {int len wordsDict.length;for(int i 0;i< len;i){String word wordsDict[i];…

Kafka基本原理及使用

目录 基本概念 单机版 环境准备 基本命令使用 集群版 消息模型 成员组成 1. Topic&#xff08;主题&#xff09;&#xff1a; 2. Partition&#xff08;分区&#xff09;&#xff1a; 3. Producer&#xff08;生产者&#xff09;&#xff1a; 4. Consumer&#xff08;…

2023年12月20日学习总结

今日to do list&#xff1a; 学习kaggle中store sales中的dart forcasting&#x1f3af; 大概搜集一个声纹识别的报告&#xff08;老师给的新项目&#x1f62d;&#xff09; 学习时不刷手机 okkkkkkkkkkkkkk 开始&#x1f44d; 1. 时间序列预测- a complete guide 总结一下这…

Vim:文本编辑的强大利器

Vim&#xff1a;文本编辑的强大利器 概述1. 工作模式1.1 普通模式1.2 插入模式1.3 可视模式 2. 代码示例2.1 移动光标2.2 复制和粘贴2.3 查找和替换 3. 应用场景结语 概述 Vim&#xff08;Vi Improved&#xff09;是一款强大的文本编辑器&#xff0c;广泛应用于Linux和Unix系统…

架构设计到底是什么?

文章目录 架构设计有哪些内容&#xff1f;架构原理与技术认知分布式技术原理与设计中间件常用组件的原理和设计问题数据库原理与设计问题分布式缓存原理与设计问题互联网高性能高可用设计问题 技术认知架构分析问题分析能力边界 架构设计&#xff0c;是中高级研发工程师逃不开的…

LabVIEW开发振动数据分析系统

LabVIEW开发振动数据分析系统 自动测试系统基于LabVIEW平台设计&#xff0c;采用了多种高级硬件设备。系统的硬件组成包括PCB振动加速度传感器&#xff0c;这是一种集成了传统压电加速度传感器和电荷放大器的先进设备&#xff0c;能够直接与采集仪器连接。此外&#xff0c;系统…

教师的职业素养有哪些

教师职业素养的重要性不言而喻。一个优秀的教师不仅需要具备专业知识&#xff0c;还需要具备一些基本的职业素养。 具备高尚的职业道德。作为教育工作者&#xff0c;教师应该以身作则&#xff0c;树立良好的榜样。他们应该尊重学生、关心学生、热爱学生&#xff0c;以自己的言行…

15 使用v-model绑定单选框

概述 使用v-model绑定单选框也比较常见&#xff0c;比如性别&#xff0c;要么是男&#xff0c;要么是女。比如单选题&#xff0c;给出多个选择&#xff0c;但是只能选择其中的一个。 在本节课中&#xff0c;我们演示一下这两种常见的用法。 基本用法 我们创建src/component…

测试自动化平台 | 测试开发工程师的进阶之路

一、测试工程师的现状 很多测试小伙伴在工作中有时会比较迷茫&#xff0c;不知该怎样突破瓶颈&#xff0c;更好的发展。 那么测试人员究竟该如何打破瓶颈继续向上提升呢&#xff1f;如果你苦于不知所措&#xff0c;又满怀斗志向上的话&#xff0c;不妨一起聊聊。测试职业发展…

(PC+WAP)装修设计公司网站模板 家装公司网站源码下载

(PCWAP)装修设计公司网站模板 家装公司网站源码下载 PbootCMS内核开发的网站模板&#xff0c;该模板适用于装修设计、家装公司类等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b; PCWAP&#xff0c;同一个后台&#xff0c…

暴雨AI服务器:推动大模型算力底座发展

语言大模型作为人工智能领域的重要分支&#xff0c;其强大的自然语言处理能力和模仿人类的对话决策能力&#xff0c;正逐渐成为人们的关注焦点。近日&#xff0c;据央视新闻报道&#xff0c;工业和信息化部赛迪研究院数据显示&#xff0c;今年我国语言大模型市场规模实现较快提…

D : B DS二叉排序树_树中第k小的元素

Description 给定一个二叉排序树和一个整数k&#xff0c;要求输出树中第k个最小元素(k从1开始计数)。 Input 第一行输入t&#xff0c;表示有t个测试样例。 第二行起&#xff0c;首先输入n&#xff0c;接着输入n个整数表示一个二叉排序树&#xff0c;接着输入k。 以此类推共…

分段函数1_分支结构 C语言xdoj112

题目描述: 编写程序计算分段函数f(x)的值。 输入格式&#xff1a;输入实数x的值 输出格式&#xff1a;输出f(x)的值&#xff0c;结果保留两位小数。 示例&#xff1a; 输入&#xff1a;4 输出&#xff1a;2.00 #include <stdio.h> #include <math.h>//分段函数1_分…

Linux常用基础命令(二)

查看当前的工作目录的路径--pwd 列表显示目录内容--ls 切换工作目录--cd 1.切换用户--su 格式&#xff1a; su 用户名 注意&#xff1a;普通用户切换到管理员用户需要输入密码&#xff0c;管理员用户切换到普通用户不需要输入密码&#xff0c;普通用户之间切换也要输入密码…

【漏洞复现】Apache Struts CVE-2023-50164

Struts2 官方披露 CVE-2023-50164 Apache Struts 文件上传漏洞&#xff0c;攻击者可利用该漏洞污染相关上传参数导致目录遍历&#xff0c;在具体代码环境中可能导致上传 Webshell&#xff0c;执行任意代码。 漏洞描述 Apache Struts2 是一个开源的 Java Web 应用程序开发框架&a…

【目标检测实验系列】YOLOv5创新点改进:融合高效轻量级网络结构GSConv,减轻模型复杂度的同时保持检测精度!(内含源代码,超详细改进代码流程)

自我介绍&#xff1a;本人硕士期间全程放养&#xff0c;目前成果:一篇北大核心CSCD录用,两篇中科院三区已见刊&#xff0c;一篇中科院三区在投。如何找创新点&#xff0c;如何放养过程厚积薄发&#xff0c;如何写中英论文&#xff0c;找期刊等等。本人后续会以自己实战经验详细…

stable diffusion webui之lora调用

1.触发词底模lora效果最好&#xff08;分数不一定要取到1&#xff0c;0.8也行&#xff09;&#xff1b; 2.引用时一定要使用<lora:>&#xff0c;例如<lora:C4D_geometry_bg_v2.5:0.8>&#xff1b; "prompt": "(masterpiece:1.3), (best quality:1.…