binary search
array
accumulate
geometry
]
Leetcode 0644 Maximum Average Subarray II
Problem statement
https://leetcode.com/problems/maximum-average-subarray-ii/
Solution 1
Let us first understand how to answer to question: is there subarray of length >= k, such that its average is >= T. It means, that if we subtract T from all numbers, then we need to find subarray with length >= k with sum >= 0. It can be done in O(n): evaluate cumulative sums and then we need to keep minimum among first i-k numbers and check if nums[i] more than this minimum. Then we do binary search on these problems, looking for T.
Complexity
Overall time complexity is O(n * log M), where $M$ is sum of all absolute values of array. Also note, that we need to use not integer beg and end to converge to 10^{-5}.
Code
class Solution:
def findMaxAverage(self, nums, k):
n = len(nums)
def checkSum(nums, T):
nums = [0] + list(accumulate([i-T for i in nums]))
minim = float("inf")
for i in range(k, n+1):
minim = min(minim, nums[i-k])
if nums[i] >= minim: return True
return False
beg, end = -10000, 10000
while end - beg > 1e-5:
mid = (beg + end)/2
if checkSum(nums, mid):
beg = mid
else:
end = mid
return beg
Solution 2
There is also very interesting solution, using convex hulls with $O(n)$ complexity, where I understand only idea, solution is quite difficult. Idea is to interpret our data as finding maximum of (S_i - S_j)/(i-j), so we can interpret (i, S_i) as points on plane. I think it is also similar to idea of monotonic deque.
Complexity
Time complexity is O(n), space as well.
Code
class Solution:
def findMaxAverage(self, nums, k):
n = len(nums)
P = [0] + list(accumulate(nums))
def d(x, y):
return (P[y+1] - P[x]) / (y+1-x)
hull = deque()
ans = float("-inf")
for j in range(k-1, n):
while len(hull) >= 2 and d(hull[-2], hull[-1]-1) >= d(hull[-2], j-k):
hull.pop()
hull.append(j-k+1)
while len(hull) >= 2 and d(hull[0], hull[1]-1) <= d(hull[0], j):
hull.popleft()
ans = max(ans, d(hull[0], j))
return ans