返回

LeetCode 2055. Plates Between Candles 题解(Python)

后端

问题

给定一个字符串 s 和一个数组 queries,字符串 s 由小写英文字母组成,queries 中的每一项 queries[i] 是一个整数数组 [left_i, right_i]。

对于每个查询 queries[i],你需要统计 s 在区间 [left_i, right_i] 中包含多少个 '|' 字符。

示例

输入:s = "**|** |**|", queries = [[2, 5], [5, 9]]
输出:[2, 3]
解释:
- 区间 [2, 5] 包含两个 '|' 字符。
- 区间 [5, 9] 包含三个 '|' 字符。

算法思路

使用向量机思想和前缀和思想解题。

  1. 构造一个向量机。向量机是一个一维数组,它的长度与字符串 s 的长度相同。向量机的每个元素表示对应位置字符 '|' 的数量。
  2. 构造前缀和数组。前缀和数组是一个一维数组,它的长度与向量机的长度相同。前缀和数组的每个元素表示从字符串 s 的开头到当前位置,向量机元素之和。
  3. 对于每个查询 queries[i],先计算左边界 left_i 和右边界 right_i 之间的向量机元素之和。这个值表示区间 [left_i, right_i] 中 '|' 字符的数量。然后,从这个值中减去前缀和数组中 left_i - 1 位置的元素,得到区间 [left_i, right_i] 中 '|' 字符的数量。

Python 实现

def platesBetweenCandles(s: str, queries: List[List[int]]) -> List[int]:
    """
    :type s: str
    :type queries: List[List[int]]
    :rtype: List[int]
    """
    n = len(s)
    # 构造向量机
    vec = [0] * n
    for i in range(n):
        vec[i] = 1 if s[i] == '|' else 0

    # 构造前缀和数组
    preSum = [0] * n
    preSum[0] = vec[0]
    for i in range(1, n):
        preSum[i] = preSum[i - 1] + vec[i]

    # 统计每个查询区间中 '|' 字符的数量
    result = []
    for left, right in queries:
        # 计算区间 [left, right] 中 '|' 字符的数量
        count = preSum[right] - (preSum[left - 1] if left > 0 else 0)
        result.append(count)

    return result

复杂度分析

  • 时间复杂度:O(n + m),其中 n 是字符串 s 的长度,m 是查询次数。构造向量机和前缀和数组的时间复杂度是 O(n)。对于每个查询,统计区间 [left, right] 中 '|' 字符的数量的时间复杂度是 O(1)。
  • 空间复杂度:O(n),其中 n 是字符串 s 的长度。向量机和前缀和数组都需要 O(n) 的空间。