Related: Minimum Size Subarray Sum
Intuition
- I started this problem by attempting a nested for loop approach, which got a TLE.
- I then did a Backtracking based approach in which I went backwards from the last element and passed computations up to the first index, which also got TLE since I am essentially doing the same thing as a double for loop but recursively.
- I then solved Minimum Size Subarray Sum which helped me understand why we must use right - left + 1 format, since left can be past right by one, but right will catch up immediately after due to the for loop, as opposed to my Original which required right - left.
- The main point of this problem is that you multiply the product, and then when you reach a point where your window contains a product k, you slide from left to right until your window contains a product less than k. Once you have done that, instead of recursively starting from the left + 1 index of that array and counting the number of subarrays, you can do right - left + 1, which essentially takes the size of your window which is how many there would be in the first place.
- For example, if you have [5,2,6], then you would have to take [5], [5,2], [2], [2,6], and [6] = 5 count, but instead you do 3 + 2 since you would find 3 on the first and 2 on the 2nd iteration of [2,6].
Note
This only works when numbers are positive and all integers.
Complexity
Runtime
(N + N) with Sliding Window since you have at most N divisions of prod and N iterations of the outer for loop.
Space
due to just axillary variables
Code
Sliding Window
class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
l = 0
count = 0
prod = 1
for r in range(len(nums)):
prod *= nums[r]
while l <= r and prod >= k:
prod /= nums[l]
l += 1
count += r - l + 1
return countBacktracking (TLE)
class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
n = len(nums)
count = 0
def r(index):
nonlocal count
if index >= n:
return deque([])
cur = nums[index]
if cur >= k:
return deque([])
count += 1
cur_products = deque([cur])
old_products = r(index + 1)
for _ in range(len(old_products)):
computation = cur * old_products.popleft()
if computation >= k:
break
count += 1
cur_products.append(computation)
return cur_products
r(0)
return countIterative (TLE)
class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
count = 0
for i, num in enumerate(nums):
cur = []
product = 1
for j in range(i, len(nums)):
product *= nums[j]
if product >= k:
break
cur.append(nums[j])
count += 1
return count
