算法-滑动窗口类型

6666

滑动窗口

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

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

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

Array: [1, 3, 2, 6, -1, 4, 1, 8, 2], K=51、对于前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 '是输入数组中数字的计数。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

netsdk1004 找不到资产文件“d:\vs-code\consoleapp1\consoleapp1\obj\project.assets.json”

今天学C#遇到一个问题记录下 创建如上所示的项目后运行出错&#xff1a; netsdk1004 找不到资产文件“d:\vs-code\consoleapp1\consoleapp1\obj\project.assets.json”。运行 nuget 包还原以生成此文件。 consoleapp1 c:\program files\dotnet\sdk\8.0.100\sdks\microsoft.net…

【单调栈】LeetCode:1944队列中可以看到的人数

作者推荐 【贪心算法】【中位贪心】.执行操作使频率分数最大 题目 有 n 个人排成一个队列&#xff0c;从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights &#xff0c;每个整数 互不相同&#xff0c;heights[i] 表示第 i 个人的高度。 一个人能 看到 他右边另一个人…

智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.黑寡妇算法4.实验参数设定5.算法结果6.参考文…

【ECharts】折线图

文章目录 折线图1折线图2折线图3示例 参考&#xff1a; Echarts官网 Echarts 配置项 折线图1 带X轴、Y轴标记线&#xff0c;其中X轴是’category’ 类目轴&#xff0c;适用于离散的类目数据。 let myChart echarts.init(this.$refs.line_chart2); let yList [400, 500, 6…

QEMU源码全解析 —— virtio(19)

接前一篇文章&#xff1a; 上回书继续讲解virtio_pci_driver的probe回调函数virtio_pci_probe()&#xff0c;在讲到第5段代码的时候&#xff0c; if (force_legacy) {rc virtio_pci_legacy_probe(vp_dev);/* Also try modern mode if we cant map BAR0 (no IO space). */if (r…

探索数据宇宙之飞船 -- python进阶函数numpy

导读&#xff1a;NumPy以其强大的多维数组对象和广泛的数学函数库著称。这些特性使得NumPy成为不仅在学术研究&#xff0c;也在工业界广泛应用的工具。无论是机器学习算法的开发、数据分析、还是复杂的数学模型的构建&#xff0c;NumPy都扮演着举足轻重的角色。 目录 Numpy简…

凝思虚拟机网络配置

1、输入验证码激活&#xff0c;不激活不能使用网络服务 2、启用网卡 ifconfig eth0 up 3、配置网络 vi /etc/network/interfaces&#xff0c;填写网卡eth0相关信息 auto eth0 allow-hotplug eth0 iface eth0 inet static address 10.1.104.210 netmask 255.255.0.0…

2-负载均衡、反向代理

负载均衡、反向代理 upstream server即上游服务器&#xff0c;指Nginx负载均衡到的处理业务的服务器&#xff0c;也可以称之为real server,即真实处理业务的服务器。 对于负载均衡我们要关心的几个方面如下&#xff1a; 上游服务器配置&#xff1a;使用upstream server配置上…

2023年中国法拍房用户画像和数据分析

法拍房主要平台 法拍房主要平台有3家&#xff0c;分别是阿里、京东和北交互联平台。目前官方认定纳入网络司法拍卖的平台共有7家&#xff0c;其中阿里资产司法拍卖平台的挂拍量最大。 阿里法拍房 阿里法拍房数据显示2017年&#xff0c;全国法拍房9000套&#xff1b;2018年&a…

C++ 图论之树的重心和直径

1. 重心 什么是树的重心&#xff1f; 物理学而言&#xff0c;重心是指地球对物体中每一微小部分引力的合力作用点&#xff0c;物体受力最集中的那一个点。数学上的重心是指三角形的三条中线的交点。 树的重心也称为质点&#xff0c;有一个很官方的定义&#xff1a;如果在树中…

【jvm从入门到实战】(九) 垃圾回收(2)-垃圾回收器

垃圾回收器是垃圾回收算法的具体实现。 由于垃圾回收器分为年轻代和老年代&#xff0c;除了G1之外其他垃圾回收器必须成对组合进行使用 垃圾回收器的组合使用关系图如下。 常用的组合如下: Serial&#xff08;新生代&#xff09; Serial Old&#xff08;老年代&#xff09; Pa…

嵌入式串口输入详细实例

学习目标 掌握串口初始化流程掌握串口输出单个字符掌握串口输出字符串掌握通过串口printf熟练掌握串口开发流程学习内容 需求 串口循环输出内容到PC机。 串口数据发送 添加Usart功能。 首先,选中Firmware,鼠标右键,点击Manage Project Items 接着,将gd32f4xx_usart.c添…