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.1 <= k <= n <= 30,000.
2.Elements of the given array will be in the range [-10,000, 10,000].
1.如果没有给我们提示k的取值大小。我们给maximumAver赋初值的时候,要知道DOUBLE.MIN_VALUE;
2.java里int型数值向double强制类型转换。
- 思路。
总体思路:对每一个长度为4的subArr的数组求average,然后求出最大值maxAverage。
1.找出所有subArray的个数。
2.为各个subArray计算average
3.比较找到最大的average输出
代码如下:
public double findMaxAverage1(int[] nums, int k) {
if (k < 0 || k > nums.length) {
return 0.0;
}
// double maximumAver = Double.MIN_VALUE;
double maximumAver = -100000;
// 1.找出所有subArray的个数。
for (int i = 0; i < nums.length - k + 1; i++) {
// 2.求该subarr的average数值
double average = 0;
for (int j = i; j < i + k; j++) {
average = (average + nums[j]);
}
average /= k;
//3.比较找到最大的average输出
if (average > maximumAver) {
maximumAver = average;
}
}
return maximumAver;
}
这个解法,问题在于计算子数组的时候,有两层循环,这样效率低下。为解决这个循环次数的问题。
我们计算下一个subArray的时候,去掉头,在加入下一个数组的尾部就好说了。
public double findMaxAverage(int[] nums, int k) {
// 总体思路:对每一个长度为4的subArr的数组求average,然后求出最大值当maxAverage
// 1.找出subArr的个数=arrlen-k+1;
// 初始值位负无穷?
if (k <= 0 || k > nums.length) {
return 0.0;
}
// double maximumAver = Double.MIN_VALUE;
double maximumAver = -10000;
// 1.第一subarr的average先求出来
double average = nums[0];
if (k == 1) {
maximumAver = nums[0];
}
for (int i = 1; i < k; i++) {
average = (average + nums[i]);
}
average = average / k;
maximumAver = average;
if (nums.length > k) {
for (int i = 1; i < nums.length - k + 1; i++) {
// 2.求该下一个subarr的average数值
average = average - (double) nums[i - 1] / k;
average = average + (double) nums[i + k - 1] / k;
if (average > maximumAver) {
maximumAver = average;
}
}
}
return maximumAver;
}
// if (nums[i - 1] > nums[i + k - 1]) {
// continue;
// }
这段注释的原因,大家可以思考一下,原本想的是,如果nums[i - 1] > nums[i + k - 1]),那么这个子数组就抛弃不去计算。结果就造成,接下来运行的时候的逻辑错误。
-再第二种方式中改进,让代码更加清晰
1.for循环的起始位置设置的可读性不好
2.可以先只用算出一个数组的累加和,而不必每次都算出average,最后返回的是数组和最大的subArray的average即可。
代码如下:
public double findMaxAverage(int[] nums, int k) {
long sum = 0;
//1计算第一个子数组的和。
for (int i = 0; i < k; i++) sum += nums[i];
long max = sum;
//2.计算出**其他的子数**(sub1除外)组个数:(nums.length-k)
for (int i = k; i < nums.length; i++) {
//3.计算出子数组的和。去头加尾。
sum += nums[i] - nums[i - k];
//4.选择和大的记录下来
max = Math.max(max, sum);
}
return max / 1.0 / k;
}
到此,这个问题就完美解决了。
工具:
字数组的个数为:(nums.length-k+1)
子数组循环用(int i = k; i < nums.length; i++) 便于定下标。
三种方法的完整代码如下:
package leet.array;
public class MaxAverSbuArr {
public double findMaxAverage(int[] nums, int k) {
// 总体思路:对每一个长度为4的subArr的数组求average,然后求出最大值当maxAverage
// 1.找出subArr的个数=arrlen-k+1;
// 初始值位负无穷?
if (k <= 0 || k > nums.length) {
return 0.0;
}
// double maximumAver = Double.MIN_VALUE;
double maximumAver = -10000;
// 1.第一subarr的average先求出来
double average = nums[0];
if (k == 1) {
maximumAver = nums[0];
}
for (int i = 1; i < k; i++) {
average = (average + nums[i]);
}
average = average / k;
maximumAver = average;
if (nums.length > k) {
for (int i = 1; i < nums.length - k + 1; i++) {
// 2.求该下一个subarr的average数值
// if (nums[i - 1] > nums[i + k - 1]) {
// continue;
// }
average = average - (double) nums[i - 1] / k;
average = average + (double) nums[i + k - 1] / k;
if (average > maximumAver) {
maximumAver = average;
}
}
}
return maximumAver;
}
public double findMaxAverage1(int[] nums, int k) {
if (k < 0 || k > nums.length) {
return 0.0;
}
// double maximumAver = Double.MIN_VALUE;
double maximumAver = -100000;
for (int i = 0; i < nums.length - k + 1; i++) {
// 2.求该subarr的average数值
double average = 0;
for (int j = i; j < i + k; j++) {
average = (average + nums[j]);
}
average /= k;
if (average > maximumAver) {
maximumAver = average;
}
}
return maximumAver;
}
public double findMaxAverage2(int[] nums, int k) {
long sum = 0;
for (int i = 0; i < k; i++) sum += nums[i];
long max = sum;
for (int i = k; i < nums.length; i++) {
sum += nums[i] - nums[i - k];
max = Math.max(max, sum);
}
return max / 1.0 / k;
}
public static void main(String[] args) {
MaxAverSbuArr maxAverSbuArr = new MaxAverSbuArr();
int[] a = { 1, 12, -5, -6, 50, 3 };
int k = 1;
System.out.println(maxAverSbuArr.findMaxAverage1(a, k));
System.out.println(maxAverSbuArr.findMaxAverage(a, k));
System.out.println(maxAverSbuArr.findMaxAverage2(a, k));
}
}