算法643. Maximum Average Subarray I

来源:互联网 发布:日志服务器端口 编辑:程序博客网 时间:2024/05/19 20:39

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));    }}
原创粉丝点击