Given an array with positive and negative numbers, find the?maximum average subarray?which length should be greater or equal to given length?k.
思路:
對平均值進(jìn)行二分。一個數(shù)組平均的最大不會超過數(shù)組最大值,也不會低于數(shù)組最小值。也就是說,這個平均值肯定在數(shù)組最大值和最小值的范圍區(qū)間內(nèi)。
用前綴和數(shù)組判斷是否數(shù)組中是否有一段長度大于等于k的子數(shù)組,平均數(shù)大于等于mid。如果存在,就把left=mid,如果不存在就把right=mid。這樣不斷所有l(wèi)和r的距離,直到重合。left 就是所能找到的最大平均值。
復(fù)雜度:
時間:?O(nlog(max_val?min_val))O(nlog(max_val?min_val))
空間:O(n)
public double maxAverage(int[] nums, int k) {
? ? ? ?double result = 0.0;
? ? ? ? if(nums == null || nums.length < k) {
? ? ? ? ? ? ?return result;
? ? ? ? ?}
? ? ? ? ?double l = Integer.MAX_VALUE;
? ? ? ? ?double r = Integer.MIN_VALUE;
? ? ? ? ?//find the largest number and smallest number in the array
? ? ? ? ? for(int i = 0; i < nums.length; i++){
? ? ? ? ? ? ? ? if(nums[i] < l) {
? ? ? ? ? ? ? ? ? ? ? l = nums[i];
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if(nums[i] > r){
? ? ? ? ? ? ? ? ? ? ? r = nums[i];
? ? ? ? ? ? ? ?}
? ? ? ? ? }
? ? ? ? ? while(r - l >= 1e-6){
? ? ? ? ? ? ? ? ?double mid = (l + r) / 2.0;
? ? ? ? ? ? ? ? if(check_valid(nums, mid, k)){
? ? ? ? ? ? ? ? ? ? ?l = mid;
? ? ? ? ? ? ? ? ?}else{
? ? ? ? ? ? ? ? ? ? r = mid;
? ? ? ? ? ? ? ?}
? ? ? ? }
? ? ? ? return l;
? ? ?}
? ? ? private boolean check_valid(int nums[], double average, int k) {
? ? ? ? ? ? int n = nums.length;
? ? ? ? ? ? double min_pre = 0;
? ? ? ? ? ? double[] sum = new double[n + 1];
? ? ? ? ? ? sum[0] = 0;
? ? ? ? ? ? ?for (int i = 1; i <= n; ++i) {
? ? ? ? ? ? ?// 原數(shù)組中的每一個數(shù)減去這個mid
? ? ? ? ? ? ? ? ? sum[i] = sum[i - 1] + nums[i - 1] - average;
? ? ? ? ? ? ? ? ?if (i >= k && sum[i] - min_pre >= 0) {
? ? ? ? ? ? ? ? ? ? ? ?return true;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?if (i >= k) ?
? ? ? ? ? ? ? ? ? ? ? ? ?min_pre = Math.min(min_pre, sum[i - k + 1]);
? ? ? ? ? }
? ? ? ? ? ?return false;
? }