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

Day8--滑动窗口与双指针--1004. 最大连续1的个数 III,1658. 将 x 减到 0 的最小操作数,3641. 最长半重复子数组

Day8–滑动窗口与双指针–1004. 最大连续1的个数 III,1658. 将 x 减到 0 的最小操作数,3641. 最长半重复子数组

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

滑动窗口相当于在维护一个队列。右指针的移动可以视作入队,左指针的移动可以视作出队

不定长滑动窗口主要分为三类:求最长子数组,求最短子数组,求子数组个数。

今天的题目类型是:求最长子数组。

1004. 最大连续1的个数 III

思路【我】:

题意:窗口中最多有k个0

不定长滑动窗口三步曲:入–出–更新

class Solution {public int longestOnes(int[] nums, int k) {// 题意:窗口中最多有k个0int n = nums.length;int zero = 0;int left = 0;int maxLen = 0;for (int i = 0; i < n; i++) {// 1,入if (nums[i] == 0) {zero++;}// 2,出while (zero > k) {if (nums[left] == 0) {zero--;}left++;}// 3,更新maxLen = Math.max(maxLen, i - left + 1);}return maxLen;}
}

附加题:顺便把这两题也做了吧,几乎是复制过去就能提交。487. 最大连续1的个数 II和485. 最大连续 1 的个数。

1658. 将 x 减到 0 的最小操作数

思路【灵艾山茶府】:

逆向思维:要选头尾的元素相加等于x,也就是中间的元素相加等于total-x。

要使头尾相加的元素最少,也就是中间的窗口尽量长——也就是求多大的窗口可以累计和为total-x

  1. 使用Arrays.stream(nums).sum()求和,记为total
    • 如果x比total还大,没办法,返回-1
    • 要求的total-x定义为need。如果need==0,答案就是要把整个数组都删掉(这里要单独讨论,否则need为0,就求不到窗口了)
  2. 不定长滑动窗口三步曲:入–出–更新
    1. 更新(注意不能一找到need==sum就返回,要找最大的窗口)
  3. 如果maxLen有值(不再为0),也就是中间窗口能凑成need,就是有恰好。否则就是凑不成,返回-1。
class Solution {public int minOperations(int[] nums, int x) {int n = nums.length;// 思路:逆向思维:要选头尾的元素相加等于x,也就是中间的元素相加等于total-x// 要使头尾相加的元素最少,也就是中间的窗口尽量长——也就是求多大的窗口可以累计和为total-x// 使用Arrays.stream(nums).sum()求和int total = Arrays.stream(nums).sum();// 如果x比total还大,没办法,返回-1if (x > total) {return -1;}// 要求的total-x定义为needint need = total - x;// 如果need==0,答案就是要把整个数组都删掉(这里要单独讨论,否则need为0,就求不到窗口了)if (need == 0) {return n;}// 初始化int left = 0;int maxLen = 0;int sum = 0;// 开始滑动窗口for (int i = 0; i < n; i++) {// 1,入sum += nums[i];// 2,出while (left < n && sum > need) {sum -= nums[left];left++;}// 3,更新(注意不能一找到need==sum就返回,要找最大的窗口)if (sum == need) {maxLen = Math.max(maxLen, i - left + 1);}}// 如果maxLen有值,也就是中间窗口能凑成need,就是有恰好。否则就是凑不成,返回-1return maxLen != 0 ? n - maxLen : -1;}
}

简洁版:

class Solution {public int minOperations(int[] nums, int x) {int n = nums.length;int total = Arrays.stream(nums).sum();if (x > total) {return -1;}int need = total - x;if (need == 0) {return n;}int left = 0;int maxLen = 0;int sum = 0;for (int i = 0; i < n; i++) {sum += nums[i];while (left < n && sum > need) {sum -= nums[left];left++;}if (sum == need) {maxLen = Math.max(maxLen, i - left + 1);}}return maxLen != 0 ? n - maxLen : -1;}
}

3641. 最长半重复子数组

思路【我】:

  1. 利用map记录窗口内各个元素出现的次数。

  2. 利用set<元素>,记录窗口内,出现次数>1,也就是“重复”的元素

  3. 不定长滑动窗口三步曲:入–出–更新。

    1. 入。如果同一个元素数量大于1(重复),加入到set
    2. 出。如果set的元素,大于k个,不符合窗口要求,收缩窗口直到窗口合法
      • 减到为0的不用管,只需要关注原来大于1(重复)的元素,现在减到1了,就是不重复了
    3. 更新maxLen
class Solution {public int longestSubarray(int[] nums, int k) {int n = nums.length;int left = 0;int maxLen = 0;int[] map = new int[100001];Set<Integer> set = new HashSet<>();// 开始滑动窗口for (int i = 0; i < n; i++) {// 1,入。如果同一个元素数量大于1(重复),加入到setif (++map[nums[i]] > 1) {set.add(nums[i]);}// 2,出。如果set的元素,大于k个,不符合窗口要求,收缩窗口直到窗口合法while (set.size() > k) {// 减到为0的不用管,只需要关注原来大于1(重复)的元素,现在减到1了,就是不重复了if (--map[nums[left]] == 1) {set.remove(nums[left]);}left++;}// 3,更新maxLen = Math.max(maxLen, i - left + 1);}return maxLen;}
}

使用map<元素,出现次数>的版本:

class Solution {public int longestSubarray(int[] nums, int k) {int n = nums.length;int left = 0;int maxLen = 0;Map<Integer, Integer> map = new HashMap<>();Set<Integer> set = new HashSet<>();for (int i = 0; i < n; i++) {// merge(1)会返回操作后,该key对应的valueif (map.merge(nums[i], 1, Integer::sum) > 1) {set.add(nums[i]);}while (set.size() > k) {if (map.merge(nums[left], -1, Integer::sum) == 1) {set.remove(nums[left]);}left++;}maxLen = Math.max(maxLen, i - left + 1);}return maxLen;}
}
http://www.xdnf.cn/news/1324225.html

相关文章:

  • 具身智能2硬件架构(人形机器人)摘自Openloong社区
  • Next.js 中的 SEO:搜索引擎优化最佳实践
  • flutter项目适配鸿蒙
  • JMeter与大模型融合应用之构建AI智能体:评审性能测试脚本
  • 【Jenkins】03 - 自动构建和docker构建
  • MCP协议演进:从SSE到Streamable HTTP的技术革命
  • 宁波市第八届网络安全大赛初赛(REVERSE-Writeup)
  • FPGA-Vivado2017.4-建立AXI4用于单片机与FPGA之间数据互通
  • OpenTelemetry、Jaeger 与 Zipkin:分布式链路追踪方案对比与实践
  • vscode wsl解决需要用别的用户调试的问题
  • VSCode REST Client 使用总结
  • Linux下的软件编程——IPC机制
  • Linx--MySQL--安装笔记详细步骤!
  • k8sday10服务发现(1/2)
  • 数据泵实施VPS海外:跨国数据同步的完整解决方案
  • 45 C++ STL模板库14-容器6-容器适配器-优先队列(priority_queue)
  • 系统架构评估方法全景解析
  • 【Java基础常见辨析】重载与重写,深拷贝与浅拷贝,抽象类与普通类
  • LLM - MCP传输协议解读:从SSE的单向奔赴到Streamable HTTP的双向融合
  • mq存量消息如何处理
  • 【iOS】Block补充
  • RecSys:排序中的融分公式与视频播放建模
  • 数据结构(03)——线性表(顺序存储和链式存储)
  • 从哲学(业务)视角看待数据挖掘:从认知到实践的螺旋上升
  • 常见的光源频闪控制方式
  • CSDN转PDF【无水印且免费!!!】
  • 数字时代著作权侵权:一场资本与法律的博弈
  • Gartner发布2025年AI与网络安全成熟度曲线:用AI增强网络安全计划的27项技术与创新
  • C++ const
  • Swift 实战:判断点集是否关于某条直线对称(LeetCode 356)