Max Subarray Product (size k)

Max Subarray Product (size k)

Return the maximum product of any contiguous subarray of exactly length k. Assume 1 <= k <= len(nums) and that all numbers are positive (so a window's product can be maintained by multiplying in the new element and dividing out the old).

maxSubarrayProduct(nums, k)

Input format: nums | k.

Examples

[1, 2, 3, 4], k=2   // → 12   (3*4)
[2, 5, 1], k=1      // → 5
[3, 3, 3], k=2      // → 9

Walkthrough

Thinking it through

Same shape as maximum sum over fixed windows, but multiplication instead of addition. The naive approach — multiply out the next k elements for every starting position — costs O(k) per window, O(n·k) overall, for the same reason: neighboring windows share k-1 elements, and recomputing from scratch wastes that shared work.

Carrying the incremental idea over to products

With sums, sliding meant "add the new element, subtract the old," since addition and subtraction are inverses. Multiplication has an inverse too: division. So multiply in the newly entering element and divide out the one that just left. The overlapping middle is untouched, so there's no reason to recompute it.

Why positivity matters here

This only works cleanly because every number is positive. A zero in the window would make dividing it back out undefined. Negative numbers would make division still work mathematically, but the maximum product no longer behaves the way you'd expect — two negatives can multiply into a large positive, which is messier to reason about incrementally. Positivity guarantees dividing out the leaving element exactly undoes its contribution.

Building the approach

  1. Multiply the first k elements to get the first window's product.
  2. Treat that as your best-so-far.
  3. Slide rightward: multiply in the new element, divide out the one that just fell off the left.
  4. Compare the updated product to the best-so-far after each slide.
  5. The largest product seen is the answer.

Why this is worth it

Each slide costs O(1) instead of O(k), so the whole algorithm runs in O(n) time and O(1) extra space, versus O(n·k) for brute force. General lesson: whenever an operation has a clean inverse (addition/subtraction, multiplication/division under safe conditions), a fixed-size window can be maintained incrementally instead of rebuilt on every slide.

main.py
Console
Press Run to execute your code, or Submit to test and complete this problem.