Given an array of integers nums and an integer k, return the number of contiguous subarrays where the product of all the elements in the subarray is strictly less than k.
solutions
linear prefix product
Instead of brute-forcing every possible subarray and checking which would be , we can maintain a prefix product array, and find the longest subarray extending to the left from some index that is .
Because all values in nums are positive, we know that every shorter subarray is also valid.
# O(n^2)
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
res = 0
prefix_products = [1]
prefix = 1
for i in range(len(nums)):
prefix *= nums[i]
for j in range(i+1):
# we're ok with just a floor function here
if prefix // prefix_products[j] < k:
res += i-j+1
break
prefix_products.append(prefix)
return resprefix products w/ binary search
We notice that prefix sums is strictly non-decreasing, so we can binary search for the leftmost valid value instead of linearly searching.
# O(nlogn)
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
res = 0
prefix_products = [1]
# O(logn)
def binary_search(i, total):
# [1, 10, 50, 100, 600]
l, r = 0, i
while l <= r:
m = (l+r)//2
prev = prefix_products[m]
if total // prev < k and (m == 0 or total // prefix_products[m-1] >= k):
return m
elif total // prev >= k:
l = m + 1
else:
r = m - 1
return -1
prefix = 1
for i in range(len(nums)):
prefix *= nums[i]
left_bound = binary_search(i, prefix)
if left_bound >= 0:
res += i-left_bound+1
prefix_products.append(prefix)
return ressliding window
We can use a standard sliding window approach to achieve linear runtime.
Remember that we might have to downsize our window down to an empty window (when ) because nums[i] could be greater than .
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
res = 0
l = 0
product = 1
for r in range(len(nums)):
# add value to window
product *= nums[r]
# decrease window until valid
# (or until window is empty i.e. l = r+1)
while l <= r and product >= k:
product //= nums[l]
l += 1
res += r-l+1
return res