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

leetcode2379:得到K个黑块的最少涂色次数(定长滑动窗口)

文章目录

  • 一、 题目描述
  • 二、 核心思路:问题转换 + 定长滑动窗口
  • 三、 代码实现与深度解析
  • 四、 关键点与复杂度分析

LeetCode2379. 得到 K 个黑块的最少涂色次数,【难度:简单;通过率:64.1%】,这道题的巧妙之处在于,它将一个看似需要“涂色操作”的问题,通过思维转换,变成了一个我们非常熟悉的 “计数” 问题

一、 题目描述

给你一个长度为 n,下标从 0 开始的字符串 blocksblocks[i] 要么是 'W' 要么是 'B',分别表示白色和黑色。同时给你一个整数 k,表示你想要得到的连续黑色块的数目

每一次操作中,你可以选择一个白色块将它涂成黑色

请你返回至少出现一次连续 k 个黑色块的 最少 操作次数

示例:

示例 1:

输入:blocks = "WBBWWBBWBW", k = 7
输出:3解释:
一种得到 7 个连续黑色块的方法是把第 0 ,3 和 4 个块涂成黑色
得到 blocks = "BBBBBBBWBW"
可以证明无法用少于 3 次操作得到 7 个连续的黑块
所以我们返回 3 

示例 2:

输入:blocks = "WBWBBBW", k = 2
输出:0解释:
不需要任何操作,因为已经有 2 个连续的黑块
所以我们返回 0

二、 核心思路:问题转换 + 定长滑动窗口

初看题目,可能会想到模拟涂色。但仔细思考后会发现 要使一个长度为 k 的子串全部变为黑色,需要操作的次数恰好等于这个子串中白色块 ‘W’ 的数量

因此,题目就转换成了:在字符串 blocks 中,找到所有长度为 k 的子串,哪一个子串包含的 ‘W’ 字符数量最少?

触发关键词: “子串”,可以尝试尝试滑动窗口来解决,尝试分析一个思路:

  1. 初始化窗口:首先,我们创建一个大小为 k 的窗口,覆盖字符串的前 k 个字符。我们计算出这个初始窗口中 ‘W’ 的数量,并将其作为初始的最小操作次数 ans
  2. 滑动窗口:然后,让窗口向右逐格滑动。每次滑动,我们都高效地更新窗口内 ‘W’ 的数量:
    • 如果离开窗口的左侧字符是 ‘W’,则计数减 1
    • 如果进入窗口的右侧新字符是 ‘W’,则计数加 1
  3. 更新结果:每次滑动后,我们都将当前窗口的 ‘W’ 数量与已知的最小值 ans进行比较,并随时更新 ans
  4. 最终结果:遍历完整个字符串后,ans 就是所有长度为 k 的子串中 ‘W’ 的最少数量,即题目的答案

三、 代码实现与深度解析

class Solution {public int minimumRecolors(String blocks, int k) {// 转为字符数组,提高效率char[] arr = blocks.toCharArray();// cnt: 记录当前窗口内白色 ('W') 块的数量// l: 窗口的左边界索引// ans: 记录到目前为止,所有窗口中白色块的最小数量int cnt = 0, l = 0, ans; // 步骤 1: 初始化第一个窗口(从索引 0 到 k-1)// 遍历前 k 个字符,计算初始窗口内的白色块数量for (int i = 0; i < k; i++) {// 如果当前字符是 'W',则 cnt 加 1cnt = arr[i] == 'W' ? cnt + 1 : cnt;}// 将第一个窗口的白色块数量作为初始的最小操作次数ans = cnt;// 步骤 2: 滑动窗口遍历剩余的字符串// r: 窗口的右边界索引,从 k 开始,直到数组末尾// 每次循环,窗口向右滑动一格for (int r = k; r < arr.length; r++) {// 2.1 处理滑出窗口的左侧字符 (arr[l])// 如果 arr[l] 是 'W',说明一个白色块离开了窗口,cnt 减 1// l++ 使左边界向右移动一格,为下一次循环做准备cnt = arr[l++] == 'W' ? cnt - 1 : cnt;// 2.2 处理滑入窗口的右侧字符 (arr[r])// 如果 arr[r] 是 'W',说明一个白色块进入了窗口,cnt 加 1cnt = arr[r] == 'W' ? cnt + 1 : cnt;// 2.3 更新最小操作次数// 每次窗口滑动完成后,当前窗口的白色块数量 (cnt) 可能是一个新的最小值// 将其与之前记录的 ans 比较,取较小值ans = Math.min(ans, cnt);}// 步骤 3: 返回最终结果// 循环结束后,ans 就存储了所有长度为 k 的子串中白色块的最少数量,// 这也正是题目所求的最少操作次数return ans;}
}

提交结果:
在这里插入图片描述

四、 关键点与复杂度分析

  • 思维转换:本题的关键在于将“最少操作次数”等价于“定长子串中最少的 ‘W’ 数量”
  • 定长滑动窗口:这是解决此类问题的标准模板,通过 O(1) 的更新操作,避免了对每个子串的重复计算
  • 时间复杂度O(N) 其中 N 是字符串 blocks 的长度。我们只需要遍历一次字符串
  • 空间复杂度O(1) 或 O(N) 如果将 toCharArray() 的开销计算在内,则为 O(N);如果不计,则只使用了常数个额外变量,为 O(1)
http://www.lryc.cn/news/615813.html

相关文章:

  • Boost.Asio io_service 与 线程 的分析
  • 字节:计算机存储单位
  • 算术运算符指南
  • 企业级WEB应用服务器TOMCAT — WEB技术详细部署
  • 使用Blender可视化多传感器坐标系转换
  • 从onnx模型到om模型的全自动化转化
  • 2025年APP开发趋势:4大方向重构行业格局
  • 【lucene】BlockDocsEnum 跟BlockImpactsDocsEnum 的区别
  • LeetCode 869.重新排序得到 2 的幂:哈希表+排序(一次初始化)
  • Java设计模式之开闭原则介绍与说明
  • 深入解析Go设计模式:命令模式实战
  • 分布微服务电商订单系统Rust编码开发[上]
  • Rust进阶-part6-宏
  • [激光原理与应用-224]:机械 - 机械设计与加工 - 常见的术语以及含义
  • 每日算法刷题Day60:8.10:leetcode 队列5道题,用时2h
  • 机器学习-增加样本、精确率与召回率
  • Modbus RTU转Profinet网关接在线循环Na离子实现PLC读取温度值
  • C# 中常用集合以及使用场景
  • 本地WSL部署接入 whisper + ollama qwen3:14b 总结字幕增加利用 Whisper 分段信息,全新 Prompt功能
  • Framework开发之Zygote进程2(基于开源的AOSP15)--init.rc在start zygote之后的事情(详细完整版逐行代码走读)
  • 《解锁 C++ 基础密码:输入输出、缺省参数,函数重载与引用的精髓》
  • 【Linux | 网络】数据链路层
  • 九、Linux Shell脚本:运算符与表达式
  • 开启单片机
  • 服务器硬件电路设计之 I2C 问答(三):I2C 总线上可以接多少个设备?如何保证数据的准确性?
  • 笔试——Day34
  • 亚麻云之全球加速器——CloudFront(CDN)服务入门
  • 【Docker实战】Spring Boot应用容器化
  • ShadowKV 机制深度解析:高吞吐长上下文 LLM 推理的 KV 缓存“影子”方案
  • Python爬虫-爬取政务网站的文档正文内容和附件数据