算法643. Maximum Average Subarray I

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));

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值