1352. 最后 K 个数的乘积
大约 3 分钟
---
1352. 最后 K 个数的乘积
- 标签:设计、队列、数组、数学、数据流
- 难度:中等
题目链接
题目大意
描述:实现一个 ProductOfNumbers 类,支持以下操作:
ProductOfNumbers()初始化对象。add(int num)将数字 添加到当前数字列表末尾。getProduct(int k)返回当前列表中最后 个数字的乘积。
说明:
- 。
- 。
- 最多调用 和 共 次。
示例:
- 示例 1:
输入:
["ProductOfNumbers","add","add","add","add","add","getProduct","getProduct","getProduct","add","getProduct"]
[[],[3],[0],[2],[5],[4],[2],[3],[4],[8],[2]]
输出:
[null,null,null,null,null,null,20,40,0,null,32]
解释:
ProductOfNumbers productOfNumbers = new ProductOfNumbers();
productOfNumbers.add(3); // [3]
productOfNumbers.add(0); // [3,0]
productOfNumbers.add(2); // [3,0,2]
productOfNumbers.add(5); // [3,0,2,5]
productOfNumbers.add(4); // [3,0,2,5,4]
productOfNumbers.getProduct(2); // 返回 20 。最后 2 个数字的乘积是 5 * 4 = 20
productOfNumbers.getProduct(3); // 返回 40 。最后 3 个数字的乘积是 2 * 5 * 4 = 40
productOfNumbers.getProduct(4); // 返回 0 。最后 4 个数字的乘积是 0 * 2 * 5 * 4 = 0
productOfNumbers.add(8); // [3,0,2,5,4,8]
productOfNumbers.getProduct(2); // 返回 32 。最后 2 个数字的乘积是 4 * 8 = 32解题思路
思路 1:前缀积
1. 核心思想
如果所有数字都 ,可以用前缀积数组轻松求解:
- 表示前 个数的乘积
- 最后 个数的乘积 =
但本题允许 。加入 后,从 之后的所有前缀积都会变成 。
解决方法:遇到 时重置前缀积数组,清空之前的积累。这样 时只需检查 是否超出数组范围。
2. 具体步骤
初始化:
- ,存储前缀积。初始 表示空集的乘积。
:
- 如果 :重置 (之前的所有积累作废)
- 否则:
:
- 如果 :说明最后 个数中包含了 ,返回
- 否则:返回
3. 正确性证明
遇到 时重置是核心所在。因为 之后的乘积不受 之前数字的影响(任何数乘 都是 ),而且题目只要求最后 个数的乘积。如果 跨过了 的位置,结果必然是 。
4. 举例说明
以操作序列 add(2), add(3), add(0), add(5), add(4), getProduct(2), getProduct(3) 为例:
| 操作 | prefix 数组 |
|---|---|
| 初始 | [1] |
| add(2) | [1, 2] |
| add(3) | [1, 2, 6] |
| add(0) | [1](重置) |
| add(5) | [1, 5] |
| add(4) | [1, 5, 20] |
| getProduct(2) | 20 / 5 = 4 |
| getProduct(3) | k=3 ≥ len(prefix)=3,返回 0 |
思路 1:代码
class ProductOfNumbers:
def __init__(self):
self.prefix = [1] # 前缀积
def add(self, num: int) -> None:
if num == 0:
# 遇到 0,重置前缀积
self.prefix = [1]
else:
self.prefix.append(self.prefix[-1] * num)
def getProduct(self, k: int) -> int:
if k >= len(self.prefix):
return 0 # 最后 k 个数包含 0
return self.prefix[-1] // self.prefix[-k - 1]思路 1:复杂度分析
- 时间复杂度:, 和 都是 时间。
- 空间复杂度:,其中 是当前列表中非零连续数字的个数(重置清零)。
思路 2:对比与总结
本题的关键点在于 可能为 。如果数字范围保证 ,则直接使用标准前缀积即可。遇到 的重置策略是本题的巧妙之处,将问题限制在非零区间内解决, 时边界判断保证正确性。