Maximum Average Subarray
update Aug 17, 2017 18:51
Given an array consisting of n integers, find the contiguous subarray of given length k that has the maximum average value. And you need to output the maximum average value.
Example 1:
Input: [1,12,-5,-6,50,3], k = 4
Output: 12.75
Explanation: Maximum average is (12-5-6+50)/4 = 51/4 = 12.75
Note: 1 <= k <= n <= 30,000. Elements of the given array will be in the range [-10,000, 10,000].
Basic Idea:
比较好的有两种思路,前缀和 以及 sliding window。时间复杂度都是O(n)。这里贴一个前缀和的java Code。
此题的 follow up 就是 Maximum Average Subarray II,条件变成了长度不小于 k 的连续子序列的最大平均值。
Java Code:
class Solution {
public double findMaxAverage(int[] nums, int k) {
int maxSum = Integer.MIN_VALUE;
int[] sums = new int[nums.length + 1];
for (int i = 1; i < sums.length; ++i) {
sums[i] = sums[i - 1] + nums[i - 1];
if (i >= k) maxSum = Math.max(maxSum, sums[i] - sums[i - k]);
}
return maxSum / (k * 1.0);
}
}
update Nov 30, 2017
更新
更新一个Java 的 sliding window solution:
// sliding window algorithm
class Solution {
public double findMaxAverage(int[] nums, int k) {
double maxAvg = (double)Integer.MIN_VALUE;
double currSum = 0;
int left = 0, right = -1; // right 初始值为 -1 是为了令 nums[0] 被考虑在内
while (true) {
if (right - left + 1 < k) {
right++;
if (right >= nums.length) break;
currSum += nums[right];
} else { // 此时 window size 一定等于 k
maxAvg = Math.max(maxAvg, currSum / k);
currSum -= nums[left];
left++;
}
}
return maxAvg;
}
}
注意这里 sliding window 的写法,while 中第一个 if 判断是否需要扩大当前窗口(right++),else 表示当前窗口大小适宜。感觉这种写法逻辑比较清晰,比几个月前自己写的sliding window 要好理解。
再写一个 preSum 解法的 python:
class Solution:
def findMaxAverage(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: float
"""
preSum = [0] * (len(nums) + 1)
maxAvg = float('-inf')
for i in range(len(nums)):
preSum[i + 1] = preSum[i] + nums[i]
if i >= k - 1:
maxAvg = max(maxAvg, (preSum[i + 1] - preSum[i + 1 - k]) / k)
return maxAvg
update 2018-07-07 10:54:54
Update: Sliding window 最终框架
这是一直觉得比较好的 sliding window 的框架写法:
用一层while循环通过移动right指针维持window size。
class Solution {
public double findMaxAverage(int[] nums, int k) {
int left = 0, right = -1;
long max = Integer.MIN_VALUE;
long window = 0;
while (true) {
while (right - left + 1 < k) {
++right;
if (right >= nums.length) break;
window += nums[right];
}
if (right >= nums.length) break;
max = Math.max(max, window);
window -= nums[left++];
}
return (double)max / k;
}
}