Design an algorithm that accepts a stream of integers and retrieves the product of the last k
integers of the stream.
Implement the ProductOfNumbers
class:
ProductOfNumbers()
Initializes the object with an empty stream.void add(int num)
Appends the integernum
to the stream.int getProduct(int k)
Returns the product of the lastk
numbers in the current list. You can assume that always the current list has at leastk
numbers.
The test cases are generated so that, at any time, the product of any contiguous sequence of numbers will fit into a single 32-bit integer without overflowing.
Example:
Input ["ProductOfNumbers","add","add","add","add","add","getProduct","getProduct","getProduct","add","getProduct"] [[],[3],[0],[2],[5],[4],[2],[3],[4],[8],[2]] Output [null,null,null,null,null,null,20,40,0,null,32] Explanation 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); // return 20. The product of the last 2 numbers is 5 * 4 = 20 productOfNumbers.getProduct(3); // return 40. The product of the last 3 numbers is 2 * 5 * 4 = 40 productOfNumbers.getProduct(4); // return 0. The product of the last 4 numbers is 0 * 2 * 5 * 4 = 0 productOfNumbers.add(8); // [3,0,2,5,4,8] productOfNumbers.getProduct(2); // return 32. The product of the last 2 numbers is 4 * 8 = 32
Constraints:
0 <= num <= 100
1 <= k <= 4 * 104
- At most
4 * 104
calls will be made toadd
andgetProduct
. - The product of the stream at any point in time will fit in a 32-bit integer.
Follow-up: Can you implement both GetProduct
and Add
to work in O(1)
time complexity instead of O(k)
time complexity?
Approach 01:
-
C++
-
Python
#include <vector> class ProductOfNumbers { public: ProductOfNumbers() { prefixProducts = {1}; } void add(int num) { if (num == 0) prefixProducts = {1}; else prefixProducts.push_back(prefixProducts.back() * num); } int getProduct(int k) { if (k >= prefixProducts.size()) return 0; return prefixProducts.back() / prefixProducts[prefixProducts.size() - k - 1]; } private: std::vector<int> prefixProducts; };
class ProductOfNumbers: def __init__(self): self.prefixProducts = [1] def add(self, num: int) -> None: if num == 0: self.prefixProducts = [1] else: self.prefixProducts.append(self.prefixProducts[-1] * num) def getProduct(self, k: int) -> int: if k >= len(self.prefixProducts): return 0 return self.prefixProducts[-1] // self.prefixProducts[-(k + 1)]
Time Complexity:
add(num)
:Appending an element to the prefix product vector takes \( O(1) \).
getProduct(k)
:Accessing elements and performing division takes \( O(1) \).
- Overall Time Complexity:
\( O(1) \) for both operations.
Space Complexity:
- Prefix Product Storage:
Stores all prefix products, leading to \( O(N) \) space usage in the worst case.
- Auxiliary Variables:
A few integer variables are used, contributing \( O(1) \) extra space.
- Overall Space Complexity:
\( O(N) \).