最大平均值子數組

最大平均值子數組 

給出一個整數數組,有正有負。找到這樣一個子數組,他的長度大於等於 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;
	}


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