💡LeetCode题解:统计两根蜡烛之间的盘子数量(Plates Between Candles)
🧩题目描述.
在一张长桌子上,盘子 (*
) 和 蜡烛 (|
) 排成一列,形成一个字符串 s
,每个字符代表一个物体:
*
表示盘子|
表示蜡烛
同时,给出一个二维整数数组 queries
,其中 queries[i] = [left_i, right_i]
表示我们需要统计字符串 s
中 [left_i...right_i]
这个子串中两根蜡烛之间的盘子数。
注意:一个盘子只在其左边和右边都至少存在一根蜡烛时,才算是处于蜡烛之间。
示例 1:
输入:
s = "**|**|***|"
queries = [[2,5],[5,9]]
输出:
[2,3]
解释:
- queries[0] 对应的子串为 "|**|",有 2 个盘子夹在两根蜡烛中间。
- queries[1] 对应的子串为 "|***|",有 3 个盘子夹在蜡烛之间。
示例 2:
输入:
s = "***|**|*****|**||**|*"
queries = [[1,17],[4,5],[14,17],[5,11],[15,16]]
输出:
[9,0,0,0,0]
解释:
- queries[0] 涉及的子串有多个蜡烛与盘子,最终有 9 个盘子被夹在蜡烛之间。
- 其余的查询要么没有成对的蜡烛,要么中间没有盘子。
🧠解题分析
这个问题的关键在于高效地处理多个查询。暴力解法(每次查询都遍历子串统计)会超时,因此需要使用预处理 + 前缀和 + 双向扫描的方法优化。
✅我们需要解决两个问题:
- 快速确定每次查询中的有效蜡烛范围
- 即区间中最靠左的一根蜡烛
left
和最靠右的一根蜡烛right
,满足left < right
。
- 即区间中最靠左的一根蜡烛
- 快速统计两根蜡烛之间的盘子数量
- 使用前缀和数组即可做到这一点。
🚀解题方法
步骤一:预处理
- **盘子前缀和 **
**prefix_sum**
prefix_sum[i]
表示从开头到位置i-1
(即s[0:i-1]
)中的盘子数。 - 最近蜡烛索引
left_candle[i]
表示i
左侧最近的蜡烛(含自身)right_candle[i]
表示i
右侧最近的蜡烛(含自身)
步骤二:处理查询
对于每个 [left, right]
:
- 找到
left
右侧最近的蜡烛l = right_candle[left]
- 找到
right
左侧最近的蜡烛r = left_candle[right]
- 如果
l < r
,说明存在合法区间,结果为prefix_sum[r] - prefix_sum[l]
- 否则返回
0
🧪代码实现(Python)
from typing import List
class Solution:
def platesBetweenCandles(self, s: str, queries: List[List[int]]) -> List[int]:
n = len(s)
prefix_sum = [0] * (n + 1)
left_candle = [-1] * n
right_candle = [-1] * n
# 1. 构造前缀和:统计盘子数量
for i in range(n):
prefix_sum[i + 1] = prefix_sum[i] + (1 if s[i] == '*' else 0)
# 2. 从左往右找每个位置的左侧最近蜡烛
prev = -1
for i in range(n):
if s[i] == '|':
prev = i
left_candle[i] = prev
# 3. 从右往左找每个位置的右侧最近蜡烛
next = -1
for i in range(n - 1, -1, -1):
if s[i] == '|':
next = i
right_candle[i] = next
# 4. 处理查询
result = []
for left, right in queries:
l = right_candle[left]
r = left_candle[right]
if l != -1 and r != -1 and l < r:
result.append(prefix_sum[r] - prefix_sum[l])
else:
result.append(0)
return result
📈时间与空间复杂度分析
操作 | 复杂度 |
---|---|
预处理前缀和 | O(n) |
构造左右蜡烛索引 | O(n) |
每个查询处理 | O(1) |
总体时间复杂度 | O(n + q),其中 n 是字符串长度, q 是查询数 |
空间复杂度 | O(n) |
✅ 相比暴力解法(O(qn)),大大提升了效率,能够处理超大数据量。
🆚算法对比
方法 | 思路 | 查询复杂度 | 是否能通过大数据集 |
---|---|---|---|
暴力遍历 | 每次从 left 到 right 查找蜡烛并统计 | O(n) | ❌ 超时 |
前缀和 + 辅助数组 | 预处理蜡烛位置和盘子数 | O(1) | ✅ 高效通过 |
🔍示例验证
s = "**|**|***|"
queries = [[2,5],[5,9]]
# 输出: [2,3]
s = "***|**|*****|**||**|*"
queries = [[1,17],[4,5],[14,17],[5,11],[15,16]]
# 输出: [9,0,0,0,0]
运行结果完全符合预期!
📝总结
本题是前缀和与双指针结合的典型应用场景,在处理需要快速区间查询的问题时非常有用。其核心思想在于通过预处理,把多次查询的复杂度从线性降到常数。
适合考察:
- 前缀和构建
- 双向扫描
- 数组索引缓存
- 边界处理技巧