当前位置: 首页 > news >正文

Day2--滑动窗口与双指针--2090. 半径为 k 的子数组平均值,2379. 得到 K 个黑块的最少涂色次数,2841. 几乎唯一子数组的最大和

Day2–滑动窗口与双指针–2090. 半径为 k 的子数组平均值,2379. 得到 K 个黑块的最少涂色次数,2841. 几乎唯一子数组的最大和

今天要训练的题目类型是:【定长滑动窗口】,题单来自@灵艾山茶府。

2090. 半径为 k 的子数组平均值

思路【我】:

  1. 先让数组默认填充-1,这样不用自己填充
  2. 直接让k变成我们熟知的窗口大小,在填avg的时候,再求回窗口的中心
  3. 注意元素大小,sum要用long类型
  4. 定长滑动窗口三部曲:入–更新–出。
class Solution {public int[] getAverages(int[] nums, int k) {// 直接让k变成我们熟知的窗口大小k = 2 * k + 1;int n = nums.length;// 结果集先填充-1int[] avg = new int[n];Arrays.fill(avg, -1);// 剪枝:如果n小于窗口,返回if (n < k) {return avg;}// 踩坑:没注意元素大小,累计和已经超过int上限了,要longlong sum = 0;// 开始滑动窗口for (int i = 0; i < n; i++) {// 1,右指针(i)进窗sum += nums[i];// 没到窗口大小,跳过if (i < k - 1) {continue;}// 2,更新结果集。这里要用i-k/2,找回中心位置// 因为sum是long,所以要强行转为intavg[i - k / 2] = (int) (sum / k);// 3,左指针(i-k=1)退出窗口sum -= nums[i - k + 1];}return avg;}
}

思路:

写法二:用window变量

class Solution {public int[] getAverages(int[] nums, int k) {int n = nums.length;int window = 2 * k + 1;// 结果集先填充-1int[] avg = new int[n];Arrays.fill(avg, -1);// 剪枝:如果n小于窗口,返回if (n < window) {return avg;}long sum = 0;// 开始滑动窗口for (int i = 0; i < n; i++) {// 1,右指针(i)进窗sum += nums[i];// 没到窗口大小,跳过if (i < window - 1) {continue;}// 索引在窗口中心位置avg[i - k] = (int) (sum / window);// 3,左指针(i-window+1)退出窗口sum -= nums[i - window + 1];}return avg;}
}

2379. 得到 K 个黑块的最少涂色次数

思路【我】:

定长滑动窗口模板题。

定长滑动窗口三部曲:入–更新–出。

class Solution {public int minimumRecolors(String blocks, int k) {char[] ch = blocks.toCharArray();int n = ch.length;// 初始化int minCount = Integer.MAX_VALUE;int count = 0;// 开始滑动for (int i = 0; i < n; i++) {// 1,右指针(i)入窗if (ch[i] == 'W') {count++;}// 没到窗口大小,继续if (i < k - 1) {continue;}// 2,更新if (count < minCount) {minCount = count;}// 3,左指针(i-k+1)出窗if (ch[i - k + 1] == 'W') {count--;}}return minCount;}
}

2841. 几乎唯一子数组的最大和

思路【我】:

  1. 在传统滑动窗口的基础上,多添加一个mapmap<元素,出现次数>来统计窗口内元素的出现次数,map.size()就是不同种元素的个数。
  2. 注意返回值是long类型的
  3. 定长滑动窗口三部曲:入–更新–出。
    1. 入:右指针(i)入栈,map统计<元素,出现次数>
    2. 更新,要先满足不同种元素个数大于等于m
    3. 左指针出窗,map对应要减少该元素的出现次数,如果为0,要remove掉
class Solution {public long maxSum(List<Integer> nums, int m, int k) {// 先确定是几乎唯一子数组,再求最大和。int[] arr = nums.stream().mapToInt(Integer::intValue).toArray();int n = arr.length;// 使用map<元素,出现次数>来统计窗口内,元素的出现次数,map.size()就是不同种元素的个数Map<Integer, Integer> map = new HashMap<>();// 注意要返回的是long啊,又踩坑了long sum = 0;long maxSum = 0;// 开始滑动窗口for (int i = 0; i < n; i++) {// 右指针(i)入栈,map统计<元素,出现次数>sum += arr[i];map.put(arr[i], map.getOrDefault(arr[i], 0) + 1);// 如果还不到窗口大小,继续if (i < k - 1) {continue;}// 2,更新,要先满足不同种元素个数大于等于mif (sum > maxSum && map.size() >= m) {maxSum = sum;}// 3,左指针出窗,map对应要减少该元素的出现次数,如果为0,要remove掉int out = arr[i - k + 1];sum -= out;if (map.get(out) == 1) {map.remove(out);} else {map.put(out, map.get(out) - 1);}}return maxSum;}
}

map.put(arr[i], map.getOrDefault(arr[i], 0) + 1);可以写成map.merge(arr[i], 1, Integer::sum);

其中前者需要两次哈希操作,一次获取值,一次更新值。后者只需要一次哈希操作。

因此,merge 在理论上会略快一点,尤其是在哈希表较大或哈希冲突较多的场景下,减少一次哈希操作的优势会更明显。

http://www.dtcms.com/a/335303.html

相关文章:

  • Linux软件编程:线程间通信
  • 【FreeRTOS】队列集
  • MySQL 插入数据提示字段超出范围?一招解决 DECIMAL 类型踩坑
  • 第三十七天(js前端数据加密和混淆)
  • Fixture Caliper 工具
  • GRPO(Group Relative Policy Optimization)公式速览
  • Scala面试题及详细答案100道(11-20)-- 函数式编程基础
  • 嵌入式软件架构设计之九: 双机通信之通信方式
  • 排列与组合
  • 超详细yolov8/11-obb旋转框全流程概述:配置环境、数据标注、训练、验证/预测、onnx部署(c++/python)详解
  • STM32标准库学习笔记
  • MM-Spatial和Spatial-MLLM论文解读
  • 【力扣-多数元素 JAVA/Python】
  • CD4+ T细胞激活区分抗PD-L1联合抗CTLA4疗法与单药抗PD-L1治疗的响应差异-空间最近邻分析
  • 民法学学习笔记(个人向) Part.5
  • 【最后203篇系列】032 OpenAI格式调用多模型实验
  • 39.离散化与哈希
  • 数据结构:二叉树的遍历 (Binary Tree Traversals)
  • 杂记 03
  • v-scale-scree: 根据屏幕尺寸缩放内容
  • 基于Python的电影评论数据分析系统 Python+Django+Vue.js
  • 防御保护12-14
  • tmux常用命令
  • Flamingo
  • KingbaseES主备读写分离集群安装教程
  • 字节数据流
  • 北汽新能源半年报:双品牌战略拉动销量增长,多元布局促进转化
  • PIDGen!DecodeProdKey函数分析之四个断点
  • 【大模型应用开发 3.RAG技术应用与Faiss向量数据库】
  • 【leetcode】12. 整数转罗马数字