zoukankan      html  css  js  c++  java
  • lintcode617- Maximum Average Subarray- medium

    Given an array with positive and negative numbers, find the maximum average subarray which length should be greater or equal to given length k.

     Notice

    It's guaranteed that the size of the array is greater or equal to k.

    Example

    Given a binary tree:

         1
       /   
     -5     11
     /    /  
    1   2 4    -2 
    

    return the node 11.

    二分法做,一开始你就假设一个average在最大值和最小值的中间,然后看这个average合不合格,小了去右半找,大了去左半找。

    合不合格的函数里,先存一个sum数组,保存前i个num - average的和,这样sum[n]-sum[m]就代表(n~m这几个连续数字各自与ave的差值)的和。如过出现了sum[n]-sum[m] > 0的情况,就说明你的average其实可以取得更大来获得一个更好的最大值。

    这个函数里还可以进一步优化从n方判断函数变为n判断函数。针对某个具体的sum[i],你可以跟的被减数一定要跟i隔了k个以上,也就是被减数index在i-k或之前。那么你只要试着找到sum[0]~sum[i-k]之间的最小数来作为减数就好了,因为如果这个最小数都不行,其他数就更不可能做到让sum[i]-减数>0了!所以一直用一个min_pre的变量来保存sum[0]~sum[i-k]之间的最小值,每次随着i变大不断更新该数字。

    部分解释可见http://blog.csdn.net/qq_34153219/article/details/56298842

    九章实现:

    public class Solution {
        /**
         * @param nums an array with positive and negative numbers
         * @param k an integer
         * @return the maximum average
         */
        public double maxAverage(int[] nums, int k) {
            // Write your code here
            double l = Integer.MAX_VALUE, r = Integer.MIN_VALUE;
            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 mid, 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) {
                sum[i] = sum[i - 1] + nums[i - 1] - mid;
                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;
        }
    }

    我的实现(思路模仿了的):

    public class Solution {
        /*
         * @param nums: an array with positive and negative numbers
         * @param k: an integer
         * @return: the maximum average
         */
        public double maxAverage(int[] nums, int k) {
            // write your code here
            if (nums == null) {
                return Double.NEGATIVE_INFINITY;
            }
            
            double left = Double.POSITIVE_INFINITY;
            double right = Double.NEGATIVE_INFINITY;
            for (int i = 0; i < nums.length; ++i) {
                if (nums[i] < left) {
                    left = (double)nums[i];
                }
                if (nums[i] > right) {
                    right = (double)nums[i];
                }
            }
            
            double eps = 1e-6;
            while (left + eps < right) {
                double mid = left + (right - left) / 2;
                if (canBigger(mid, nums, k)) {
                    left = mid;
                } else {
                    right = mid;
                }
            }
            
            return left;
        }
        
        private boolean canBigger(double avg, int[] nums, int k) {
            
            double[] sums = new double[nums.length];
            sums[0] = nums[0] - avg;
            for (int i = 1; i < sums.length; i++) {
                sums[i] = sums[i - 1] + nums[i] - avg;
            }
            
            double min_prev = 0;
            for (int i = k - 1; i < sums.length; i++) {
                if (sums[i] - min_prev >= 0) {
                    return true;
                }
                min_prev = Math.min(min_prev, sums[i - k + 1]);
            }
            
            return false;
        }
    }
  • 相关阅读:
    MongoDB快速入门教程 (4.1)
    MongoDB快速入门教程 (3.3)
    MongoDB快速入门教程 (3.2)
    MongoDB快速入门教程(3.1)
    MongoDB快速入门教程 (2)
    MongoDB快速入门教程 (1)
    express高效入门教程(5)
    刷过的题 分类汇总
    Binary Tree & Divide Conquer 完整笔记------part 2
    binary search完整笔记
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/7636531.html
Copyright © 2011-2022 走看看