最大平均值子数组

最大平均值子数组 

给出一个整数数组,有正有负。找到这样一个子数组,他的长度大于等于 k,且平均值最大。

 注意事项

保证数组的大小 >= k

样例

给出 nums = [1, 12, -5, -6, 50, 3], k = 3

返回 15.667 // (-6 + 50 + 3) / 3 = 15.667


   这道题可以用二分法去做。总结:所有有最大最小值去求某个值的题目,都可以用二分法。具体代码和解释见代码:

public double maxAverage(int[] nums, int k) {
		double high = Integer.MIN_VALUE;
		double low = Integer.MAX_VALUE;
		for (int n : nums) {
			if (high < n) {
				high = n;
			}
			if (low > n) {
				low = n;
			}
		}
		// 1. 最大平均子数组的平均数一定小于数组最大值,大于数组最小值,用这个最大最小去逼近
		while (high - low > 1e-6) {
			double mid = (high + low) / 2;
			if (hasBiggerSubArray(nums, k, mid)) {
				low = mid;
			} else {
				high = mid;
			}
		}
		return high;
	}

private boolean hasBiggerSubArray(int[] nums, int k, double mid) {
		double[] sum = new double[nums.length];
		double min = 0;
		sum[0] = nums[0] - mid;
		for (int i = 1; i < nums.length; i++) {
			sum[i] = sum[i - 1] + nums[i] - mid;
			if (i >= k - 1 && sum[i] > min) {// 
				return true;
			}
			if (i >= k - 1) {
				// 2.求i前面且距离i大于等于长度k的某个偏差最小值。
				// 2.1为啥找前面最小偏差呢:假定这个值为nums[j],如果这个最小偏差被后面某个偏差加大了,说明j到i这个子数组里面存在平均数比
				// mid大的,只有i到j的平均数比mid大才会使得sum[i] > sum[j](如果比mid小,sum只会越加越小);这步是这个算法的重难点
				// 2.2为啥长度要大于k才执行此逻辑:确保2.1中说的加大了偏差的子数组的长度大于等于k
				min = Math.min(min, sum[i - k + 1]);
			}
		}
		return false;
	}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章