Geometric Mean Maximum Subarray

topic description

Find the subarray with length at least and maximum geometric mean from an Narray of positive numbers of length , and output its position and size. (The geometric mean of K numbers is the Kth root of the product of K numbers) If there are multiple sub-arrays whose geometric mean is the maximum value, then output the sub-array with the smallest length. If there are multiple subarrays with the same length whose geometric mean is the maximum value, then output the first subarray.numbersL


enter description

  • The first line of input isN、L
    • NRepresented numberssize 1 ≤ N ≤ 100000 1\le N\le 1000001N100000
    • LIndicates the minimum length of a subarray 1 ≤ L ≤ N 1\le L\le N1LN
  • The following Nlines represent the number numbersin Neach line 1 0 − 9 ≤ numbers [ i ] ≤ 1 0 9 10^{-9} \le numbers[i] \le 10^9109numbers[i]109

output description

  • Output the position (counting from 0) and size of the subarray, separated by a space.

Remark

  • The use case guarantees that, except for the subarray whose geometric mean is the maximum value, the geometric mean of the other subarrays is at least 1 smaller than the maximum value 0 − 10 10^{-10}10− Multiples of 10 .

Example

use case 1

  • enter
3 2
2
2
3
  • output
1 2
  • illustrate
  • There are 3 sub-arrays with length at least 2, which are{2, 2}、{2, 3}、{2, 2, 3}
  • Among them {2, 3}, the geometric mean is the largest, so output its position 1 and length 2

use case 2

  • enter
10 2

0.2
0.1
0.2
0.2
0.2
0.1
0.2
0.2
0.2
0.2
  • output
2 2
  • illustrate
  • There are multiple subarrays of length at least 2 that have a geometric mean of 0.2, among which the shortest length is 2, and there are multiple.
  • The first subarray of length 2 and geometric mean of 0.2 is a subarray composed of two 0.2 starting from the second number

code display

    private static void maxGeoSubArray(double[] numbers, int L) {
    
    
        // 首先构造前缀积数组
        int n = numbers.length;
        double[] mul = new double[n+1];
        // 初始化第一个元素 为 0
        mul[0] = 1.0;

        // 填充前缀积数组数据
        for(int i = 0;i < n;i++) {
    
    
            mul[i + 1] = mul[i] * numbers[i];
        }

        // 初始化左右边界变量
        int l = 0,r = 0;
        // 保存最大值
        double ans = 0.0;

        //  双重遍历,去找到 最大几何平均值
        for(int i = 0;i <= n - L;i++) {
    
    
            for(int j = i + L - 1;j < n;j++) {
    
    
                // 这个时候,计算区间  [i, j] 的几何平均值 j - i + 1
                double t = mul[j+1] / mul[i];
                int len = j - i + 1;
                //  开  len 次方根
                double avg = Math.pow(t, 1.0 / len);

                // 根据备注要求,几何平均值的大小至少要保证比最大值 小 10^{-10} 次方倍
                if(Math.abs(avg - ans) > Math.max(avg, ans) / Math.pow(10, 10) && avg >= ans) {
    
    
                    if(avg == ans) {
    
    
                        int local = r - l + 1;
                        if(len > local) {
    
    
                            r = j;
                            l = i;
                        }
                    } else {
    
    
                        ans = avg;
                        r = j;
                        l = i;
                    }
                }
            }
        }

        // 最终遍历最后然后输出结果   输出  位置 和 长度
        System.out.print(l + " ");
        System.out.print(r - l + 1);
    }

Guess you like

Origin blog.csdn.net/GoNewWay/article/details/131391555