Watch 10 video solutions for Product of the Last K Numbers, a medium level problem involving Array, Math, Design. This walkthrough by Fraz has 8,321 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
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 integer num to the stream.int getProduct(int k) Returns the product of the last k numbers in the current list. You can assume that always the current list has at least k 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 <= 1001 <= k <= 4 * 1044 * 104 calls will be made to add and getProduct.Problem Overview: Design a data structure that supports two operations on a stream of integers: add(num) and getProduct(k). The second operation returns the product of the last k numbers added to the stream. The challenge is answering queries efficiently even when the stream grows large.
Approach 1: Naive Approach with Array (Add: O(1), Query: O(k) time, O(n) space)
Store every incoming number in a dynamic array. When getProduct(k) is called, iterate over the last k elements and multiply them together. The logic is straightforward: compute the product on demand using a simple loop from n - k to n - 1. This approach uses an array to keep the stream and requires no preprocessing.
The downside appears when queries are frequent or k becomes large. Each query scans up to k elements, making the worstโcase time O(k). For a long stream with many queries, this quickly becomes inefficient. Still, it works well for small inputs or when query frequency is low.
Approach 2: Prefix Products (Add: O(1), Query: O(1) time, O(n) space)
The optimized solution stores cumulative prefix products. Maintain a list where prefix[i] represents the product of all numbers from the start of the stream up to index i. When a new number arrives, append prefix[last] * num. To compute the product of the last k numbers, divide the current prefix product by the prefix value k positions earlier.
The key complication is handling zeros. If a zero appears in the stream, any product spanning that position becomes zero. The fix is simple: reset the prefix list whenever a zero is added. If the query asks for more elements than currently stored after the last zero, return 0.
This design transforms each query into constant time arithmetic. It works because multiplication over a range can be reconstructed from two prefix values, similar to prefix sums but using products. The pattern commonly appears in math and data stream problems where repeated range queries must be fast.
Recommended for interviews: Interviewers expect the prefix product approach. The brute force array method demonstrates baseline reasoning, but the optimized design shows you recognize prefix techniques and can adapt them to streaming data with edge cases like zeros. Achieving O(1) query time is the key signal of a strong solution.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Naive Array Multiplication | Add: O(1), Query: O(k) | O(n) | Useful for small streams or when query operations are rare |
| Prefix Products with Zero Reset | Add: O(1), Query: O(1) | O(n) | Best for frequent queries and large data streams |