《LeetCode热题100》---<4.子串篇三道>
本篇博客讲解LeetCode热题100道子串篇中的三道题
第一道:和为 K 的子数组
第二道:滑动窗口最大值
第三道:最小覆盖子串
第一道:和为 K 的子数组(中等)

法一:暴力枚举
class Solution {public int subarraySum(int[] nums, int target) {int count = 0;for (int start = 0; start < nums.length; ++start) {int sum = 0;for (int end = start; end >= 0; --end) {sum += nums[end];if (sum == target) {count++;}}}return count;}
}
思想比较简单,找到所有子数组的和,如果等于目标值target。那么count++
最终返回count
法二:前缀和 + 哈希表优化
class Solution {public int subarraySum(int[] nums, int target) {int count = 0, pre = 0;HashMap < Integer, Integer > map = new HashMap < > ();map.put(0, 1);for (int i = 0; i < nums.length; i++) {pre += nums[i];if (map.containsKey(pre - target)) {count += map.get(pre - target);}map.put(pre, map.getOrDefault(pre, 0) + 1);}return count;}
}
前缀和:是求解子数组的和等问题的好方法。通过累加数组中的值,使其减去数组中某个值来得到子数组的和。
前缀和用法示例:
建哈希表优化后。
前缀和: 使用pre += nums[i]; 用pre变量来累加前缀和。只需要pre即可。
因为我们只需要用累加和减去目标值target。再去哈希表中找有没有对应的值。
如果有对应的值,说明存在子数组的和为target。那么count++
最终返回conunt
第二道:滑动窗口最大值(困难)

法一:优先队列
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {int n = nums.length;PriorityQueue<int[]> pQueue = new PriorityQueue<int[]>(new Comparator<int[]>() {public int compare(int[] pair1, int[] pair2) {return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1];}});for (int i = 0; i < k; ++i) {pQueue.offer(new int[]{nums[i], i});}int[] ans = new int[n - k + 1];ans[0] = pQueue.peek()[0];for (int i = k; i < n; ++i) {pQueue.offer(new int[]{nums[i], i});while (pQueue.peek()[1] <= i - k) {pQueue.poll();}ans[i - k + 1] = pQueue.peek()[0];}return ans;}
}
- 定义一个优先队列(最大堆)
pQueue,用于存储滑动窗口内的元素。队列按照元素值降序排列,如果值相同则按索引降序排列。- 初始化队列,将数组前
k个元素加入队列。- 创建结果数组
ans,用于存储每个窗口的最大值。- 将队列顶部(最大值)的元素值存入结果数组的第一个位置。
- 从第
k个元素开始,逐步将元素加入队列,并移除不在当前滑动窗口内的元素(根据索引判断)。- 每次移动窗口后,将当前窗口的最大值(队列顶部元素值)存入结果数组相应位置。
- 最终返回结果数组。
使用优先队列高效地计算了数组中每个滑动窗口的最大值。
法二:单调队列(单调性的双端队列)
单调队列套路
- 入(元素进入队尾,同时维护队列单调性)
- 出(元素离开队首)
- 记录/维护答案(根据队首)
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {int n = nums.length;Deque<Integer> deque = new LinkedList<Integer>();for (int i = 0; i < k; ++i) {while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {deque.pollLast();}deque.offerLast(i);}int[] ans = new int[n - k + 1];ans[0] = nums[deque.peekFirst()];for (int i = k; i < n; ++i) {while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {deque.pollLast();}deque.offerLast(i);while (deque.peekFirst() <= i - k) {deque.pollFirst();}ans[i - k + 1] = nums[deque.peekFirst()];}return ans;}
}
- 初始化一个双端队列,用于存储数组元素的索引。
- 遍历数组前
k个元素,保持队列中元素对应的数组值按降序排列,并存储这些元素的索引。- 初始化结果数组
ans并将第一个窗口的最大值(队列头部的元素)存入ans的第一个位置。- 遍历数组剩余元素:
- 将新的元素索引加入队列,并移除队列中所有比当前元素小的元素的索引。
- 移除队列中不在当前窗口范围内的索引。
- 将当前窗口的最大值(队列头部的元素)存入
ans的相应位置。最终返回结果数组
ans。
法三:分块 + 预处理
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {int n = nums.length;int[] prefixMax = new int[n];int[] suffixMax = new int[n];for (int i = 0; i < n; ++i) {if (i % k == 0) {prefixMax[i] = nums[i];}else {prefixMax[i] = Math.max(prefixMax[i - 1], nums[i]);}}for (int i = n - 1; i >= 0; --i) {if (i == n - 1 || (i + 1) % k == 0) {suffixMax[i] = nums[i];} else {suffixMax[i] = Math.max(suffixMax[i + 1], nums[i]);}}int[] ans = new int[n - k + 1];for (int i = 0; i <= n - k; ++i) {ans[i] = Math.max(suffixMax[i], prefixMax[i + k - 1]);}return ans;}
}
初始化前缀最大值和后缀最大值数组:
prefixMax[i]表示从块的开始到索引i的最大值。suffixMax[i]表示从索引i到块的结束的最大值。构建前缀最大值数组:
- 遍历数组,如果索引
i是块的开始,prefixMax[i]等于nums[i]。- 否则,
prefixMax[i]等于prefixMax[i - 1]和nums[i]的最大值。构建后缀最大值数组:
- 从数组末尾遍历,如果索引
i是块的结束,suffixMax[i]等于nums[i]。- 否则,
suffixMax[i]等于suffixMax[i + 1]和nums[i]的最大值。计算每个滑动窗口的最大值:
- 遍历
ans数组,每个窗口的最大值是suffixMax[i]和prefixMax[i + k - 1]的最大值。返回结果数组:
- 返回存有每个滑动窗口最大值的结果数组
ans
第三道:最小覆盖子串(困难)

方法一:滑动窗口

class Solution {Map<Character, Integer> ori = new HashMap<Character, Integer>();Map<Character, Integer> cnt = new HashMap<Character, Integer>();public String minWindow(String s, String t) {int tLen = t.length();for (int i = 0; i < tLen; i++) {char c = t.charAt(i);ori.put(c, ori.getOrDefault(c, 0) + 1);}int l = 0, r = -1;int len = Integer.MAX_VALUE, ansL = -1, ansR = -1;int sLen = s.length();while (r < sLen) {++r;if (r < sLen && ori.containsKey(s.charAt(r))) {cnt.put(s.charAt(r), cnt.getOrDefault(s.charAt(r), 0) + 1);}while (check() && l <= r) {if (r - l + 1 < len) {len = r - l + 1;ansL = l;ansR = l + len;}if (ori.containsKey(s.charAt(l))) {cnt.put(s.charAt(l), cnt.getOrDefault(s.charAt(l), 0) - 1);}++l;}}return ansL == -1 ? "" : s.substring(ansL, ansR);}public boolean check() {Iterator iter = ori.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); Character key = (Character) entry.getKey(); Integer val = (Integer) entry.getValue(); if (cnt.getOrDefault(key, 0) < val) {return false;}} return true;}
}
初始化哈希表:
- 使用
ori哈希表记录字符串t中每个字符出现的次数。- 使用
cnt哈希表记录当前窗口中每个字符的出现次数。滑动窗口的初始化:
- 初始化左指针
l和右指针r,分别表示当前窗口的左右边界。- 初始化记录最小窗口长度的
len和最小窗口的起始和结束位置ansL和ansR。滑动窗口扩展:
- 移动右指针扩展窗口,若当前字符在
t中,将其加入cnt。缩小窗口:
- 当窗口内包含了
t中所有字符时,尝试缩小窗口:
- 如果当前窗口长度小于已记录的最小窗口长度,更新最小窗口的位置和长度。
- 移动左指针,若左指针指向的字符在
t中,将其从cnt中移除。返回结果:
- 如果找到了符合条件的窗口,返回最小窗口的子字符串,否则返回空字符串。
辅助方法
check:
- 检查当前窗口是否包含
t中所有字符,即cnt中每个字符的数量是否都不小于ori中对应的数量。
相关文章:
《LeetCode热题100》---<4.子串篇三道>
本篇博客讲解LeetCode热题100道子串篇中的三道题 第一道:和为 K 的子数组 第二道:滑动窗口最大值 第三道:最小覆盖子串 第一道:和为 K 的子数组(中等) 法一:暴力枚举 class Solution {public in…...
全国区块链职业技能大赛样题第9套前端源码
后端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746050 前端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746216 智能合约+数据库表设计:https://blog.csdn.net/Qhx20040819/article/details/140746646 登录 用户管理...
如何提高编程面试成功率:LeetCode Top 100 问题及解答解析(详细面试宝典)
以下是 LeetCode Top 100 面试必备题目及其解决方案示例。这些题目涵盖了数据结构、算法、动态规划、回溯等多种重要的面试话题。希望各位同学有所收货,早日脱离底层到达彼岸! 1. Two Sum 题目: 给定一个整数数组 nums 和一个目标值 target,…...
K-近邻和神经网络
K-近邻(K-NN, K-Nearest Neighbors) 原理 K-近邻(K-NN)是一种非参数分类和回归算法。K-NN 的主要思想是根据距离度量(如欧氏距离)找到训练数据集中与待预测样本最近的 K 个样本,并根据这 K 个…...
用EasyV全景图低成本重现真实场景,360°感受数字孪生
全景图,即借助绘画、相片、视频、三维模型等形式,通过广角的表现手段,尽可能多表现出周围的环境。避免了一般平面效果图视角单一,不能带来全方位视角的缺陷,能够全方位的展示360度球型范围内的所有景致,最大…...
【Golang 面试 - 进阶题】每日 3 题(九)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…...
孟德尔随机化、R语言,报错,如何解决?
🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收…...
一文剖析高可用向量数据库的本质
面对因电力故障、网络问题或人为操作失误等导致的服务中断,数据库系统高可用能够保证系统在这些情况下仍然不间断地提供服务。如果数据库系统不具备高可用性,那么系统就需要承担停机和数据丢失等重大风险,而这些风险极有可能造成用户流失&…...
JavaScript青少年简明教程:异常处理
JavaScript青少年简明教程:异常处理 在 JavaScript 中,异常指的是程序执行过程中出现的错误或异常情况。这些错误可能导致程序无法正常执行,甚至崩溃。ECMA-262规范了多种JavaScript错误类型,这些类型都继承自Error基类。主要的错…...
科普文:Lombok使用及工作原理详解
1. 概叙 Lombok是什么? Project Lombok 是一个 JAVA 库,它可以自动插入编辑器和构建工具,为您的 JAVA 锦上添花。再也不要写另一个 getter/setter 或 equals 等方法,只要有一个注注解,你的类就有一个功能齐全的生成器…...
飞致云开源社区月度动态报告(2024年7月)
自2023年6月起,中国领先的开源软件公司FIT2CLOUD飞致云以月度为单位发布《飞致云开源社区月度动态报告》,旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况,以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源大屏…...
mybatis-plus——实现动态字段排序,根据实体获取字段映射数据库的具体字段
前言 前端需要根据表头的点击控件可以排序,虽然前端能根据当前页的数据进行对应字段的排序,但也仅局限于实现当前页的排序,无法满足全部数据的排序,所以需要走接口的查询进行排序,获取最全的排序数据 实现方案 前端…...
redis:Linux安装redis,redis常用的数据类型及相关命令
1. 什么是NoSQL nosql[not only sql]不仅仅是sql。所有非关系型数据库的统称。除去关系型数据库之外的都是非关系数据库。 1.1为什么使用NoSQL NoSQL数据库相较于传统关系型数据库具有灵活性、可扩展性和高性能等优势,适合处理非结构化和半结构化数据,…...
JavaScript 和 HTML5 Canvas实现图像绘制与处理
前言 JavaScript 和 HTML5 的 canvas 元素提供了强大的图形和图像处理功能,使得开发者能够在网页上创建动态和交互式的视觉体验。这里我们将探讨如何使用 canvas 和 JavaScript 来处理图像加载,并在其上进行图像绘制。我们将实现一个简单的示例…...
Java之Java基础二十(集合[上])
Java 集合框架可以分为两条大的支线: ①、Collection,主要由 List、Set、Queue 组成: List 代表有序、可重复的集合,典型代表就是封装了动态数组的 ArrayList 和封装了链表的 LinkedList;Set 代表无序、不可重复的集…...
【C++BFS】1162. 地图分析
本文涉及知识点 CBFS算法 LeetCode1162. 地图分析 你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地。 请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距…...
实战:安装ElasticSearch 和常用操作命令
概叙 科普文:深入理解ElasticSearch体系结构-CSDN博客 Elasticsearch各版本比较 ElasticSearch 单点安装 1 创建普通用户 #1 创建普通用户名,密码 [roothlink1 lyz]# useradd lyz [roothlink1 lyz]# passwd lyz#2 然后 关闭xshell 重新登录 ip 地址…...
React-Native 宝藏库大揭秘:精选开源项目与实战代码解析
1. 引言 1.1 React-Native 简介 React-Native 是由 Facebook 开发的一个开源框架,它允许开发者使用 JavaScript 和 React 的编程模型来构建跨平台的移动应用。React-Native 的核心理念是“Learn Once, Write Anywhere”,即学习一次 React 的编程模型&am…...
数据结构:二叉树(链式结构)
文章目录 1. 二叉树的链式结构2. 二叉树的创建和实现相关功能2.1 创建二叉树2.2 二叉树的前,中,后序遍历2.2.1 前序遍历2.2.2 中序遍历2.2.3 后序遍历 2.3 二叉树节点个数2.4 二叉树叶子结点个数2.5 二叉树第k层结点个数2.6 二叉树的深度/高度2.7 二叉树…...
召唤生命,阻止轻生——《生命门外》
本书的目的,就是阻止自杀!拉回那些深陷在这样的思维当中正在挣扎犹豫的人,提醒他们珍爱生命,让更多的人,尤其是年轻人从执迷不悟的犹豫徘徊中幡然醒悟,回归正常的生活。 网络上抱孩子跳桥轻生的母亲&#…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
