【算法文章10| 前缀和:力扣2055题:蜡烛之间的盘子】

【算法文章10| 前缀和:力扣2055题:蜡烛之间的盘子】

题目链接:2055:蜡烛之间的盘子

这道题是力扣的一道1818分的题,大概题意是这样的:

  • 给你一个字符串,字符串里面只有两种符号:字符 '*''|' ,其中 '*' 表示 盘子'|' 表示 蜡烛
  • 然后给你一个二维的查询数组queries,对于每一个查询 queries[i] = [lefti, righti],找到 子字符串中两支蜡烛之间 的盘子的 数目
  • 返回一个整数数组 answer ,其中 answer[i] 是第 i 个查询的答案。

总结一句话:找规定区间内, 在两支蜡烛之间的盘子的数目

这道题的难点在于,对于每一个查询区间[lefti, righti],怎么找区间内的离边界最近的蜡烛的位置,也就是怎么寻找“有效边界”

思路:寻找“有效边界”

  1. 定义前缀和sum[],记录盘子的数量
  2. 定义两个数组left[] 跟 right[],他们的含义如下:
    1. left[]表示:索引i左侧(含 i)最近的 ‘|’ (蜡烛) 的索引
    2. right[]表示:索引 i 右侧(含 i)最近的 ‘|’ (蜡烛) 的索引
  3. 枚举所有的查询
    • 缩小区间范围
      • 找左端点右边的第一根蜡烛,作为新的左端点
      • 找右端点左边的第一根蜡烛,作为新的右端点

代码

classSolution{publicint[]platesBetweenCandles(String s,int[][] queries){int n = s.length();//1.前缀和sum[]记录盘子的数量int[] sum =newint[n+1];//2.left[]统计索引i(含 i)左侧最近的'|'的索引int[]left =newint[n];int lastCandle =-1;for(int i =0; i < n; i++){if(s.charAt(i)=='|'){ sum[i+1]= sum[i]; lastCandle = i;}else{ sum[i+1]= sum[i]+1;} left[i]= lastCandle;}//3.right[]统计索引i(含 i)右侧最近的'|'的索引int[]right =newint[n]; lastCandle =-1;for(int i = n-1; i >=0; i--){if(s.charAt(i)=='|'){ lastCandle = i;} right[i]= lastCandle;}int[]ans =newint[queries.length];for(int i =0; i < queries.length; i++){//找左端点右边的第一根蜡烛,作为新的左端点int l = right[queries[i][0]];//找右端点左边的第一根蜡烛,作为新的右端点int r = left[queries[i][1]];//更新答案if(l !=-1&& r !=-1&& l < r){ ans[i]= sum[r]- sum[l];}else{ ans[i]=0;}}return ans;}}


一定要理解这两句代码,这两句代码非常关键,我们的目的是:left 向右移,找到区间内的第一根蜡烛。将 right 向左移,找到区间内的最后一根蜡烛。
  • 时间复杂度: O ( n + q ) O(n + q) O(n+q)
    • 遍历字符串计算前缀和 sum 和 left 数组:O(n)
    • 遍历字符串计算 right 数组:O(n)
    • 遍历查询数组 queries:O(q)(q = queries.length)

利用具体案例帮助理解代码

场景一:区间内完全没有蜡烛

假设字符串 s = "***|***",长度为 7。查询区间为 [0, 2](即前三个星号 ***)。

  1. 预处理的结果
    • right 数组:每一个位置向右看的第一根蜡烛都在索引 3。所以 right[0] = 3
    • left 数组:前三个位置向左看都没有蜡烛。所以 left[0, 1, 2] = -1
  2. 判断
    • if (l != -1 && r != -1 && l < r)
    • 这里 r 是 -1,条件直接不成立。
    • 结果ans[i] = 0
场景二:只有一根蜡烛,或蜡烛在边缘无法包裹盘子

假设字符串 s = "***|**",查询区间为 [0, 5](整个字符串)。

  1. 预处理结果
    • right[0]:从索引 0 开始向右找,第一根蜡烛在索引 3。所以 l = 3
    • left[5]:从索引 5 开始向左找,第一根蜡烛也在索引 3。所以 r = 3
  2. 判断逻辑
    • if (l < r) → \rightarrow → 即 if (3 < 3)
    • 条件不成立(因为只有一根蜡烛,无法形成“中间”区域)。
    • 结论ans[i] = 0
场景三:区间内有蜡烛,但它们中间没盘子

假设字符串 s = "**||**",查询区间为 [0, 5]

  1. 预处理结果
    • l = right[0] → \rightarrow → 索引 2(第一根 |)。
    • r = left[5] → \rightarrow → 索引 3(第二根 |)。
  2. 前缀和计算
    • sum[2](前 2 个字符里的盘子数)是 2。
    • sum[3](前 3 个字符里的盘子数)也是 2(因为索引 2 是蜡烛,盘子数没增加)。
  3. 判断
    • l < r (2 < 3) 成立。
    • ans[i] = sum[3] - sum[2] → \rightarrow →0

如果对你有帮助,欢迎点赞、关注、收藏!

Read more

Flutter 三方库 serverpod_cli 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、全能、自动化的 Full-stack Dart (Serverpod) 后端与 HAP 端代码生成引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 serverpod_cli 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、全能、自动化的 Full-stack Dart (Serverpod) 后端与 HAP 端代码生成引擎 在鸿蒙(OpenHarmony)系统的端云一体化应用开发中,如何通过一份模型定义(YAML),即可自动生成鸿蒙(HAP)端的强类型客户端代码、数据库迁移脚本及复杂的 RPC 接口?serverpod_cli 为开发者提供了一套工业级的“全栈 Dart”构建控制台。本文将带您深入实战其在构建鸿蒙高性能云端交互层中的应用。 前言 什么是 Serverpod CLI?它不是运行在 HAP 里的库,而是运行在鸿蒙开发环境(DevEco Studio 配套主机)中的“

By Ne0inhk
全网最全Win10/11系统下WSL2+Ubuntu20.04的全流程安装指南(两种支持安装至 D 盘方式)

全网最全Win10/11系统下WSL2+Ubuntu20.04的全流程安装指南(两种支持安装至 D 盘方式)

前言 WSL2(Windows Subsystem for Linux 2)是 Windows 提供的一种轻量级 Linux 运行环境,具备完整的 Linux 内核,并支持更好的文件系统性能和兼容性。它允许用户在 Windows 系统中运行 Linux 命令行工具和应用程序,而无需安装虚拟机或双系统。 本教程将介绍 如何安装 WSL2 并将 Ubuntu-20.04 安装到 D 盘,涵盖 WSL2 的启用、Ubuntu 的下载与解压、WSL2 发行版的导入,以及普通用户的设置与安装验证。这是全网最全的 WSL2 安装与配置指南,参考了大量博客教程,并结合实践经验,整理出最实用、最详细的方法,适用于所有 Windows 10/11

By Ne0inhk

Kiro Remote SSH 无法连接远程服务器问题排查与解决

一、问题背景 在使用 Kiro(Open Remote SSH 扩展) 连接远程服务器(AlmaLinux,GPU 节点)时,出现无法连接的问题,主要报错包括: Couldn't get identities from OpenSSH agent Failed to connect to agent Unable to establish SSL connection. Error downloading server from https://prod.download.desktop.kiro.dev/... 导致 Kiro Server 无法在远程服务器安装并启动,从而连接失败。下图无法正确安装: 二、

By Ne0inhk