子区间平均值问题 | 豆包MarsCode AI刷题

125 阅读2分钟

一、问题描述

小U有一个长度为n的整数数组,并且选择了一个有理数 u/v。他现在想知道这个数组中有多少个连续的子区间,其平均值恰好等于 u/v。数组的子区间是指数组中一段连续的元素。

例如,给定数组 [2, 4, 1, 3, 2, 3] 和有理数 5/2,我们需要找出所有平均值等于 5/2 的子区间。


二、测试样例

样例1:

输入:n = 6 ,u = 5 ,v = 2 ,arr = [2, 4, 1, 3, 2, 3] 

输出:6

样例2:

输入:n = 5 ,u = 1 ,v = 1 ,arr = [1, 1, 1, 1, 1] 

输出:15

样例3:

输入:n = 4 ,u = 2 ,v = 1 ,arr = [2, 2, 2, 2] 

输出:10


三、思路

连续子区间可以用两个指针表示,i为子区间开头,j为子区间具体的数字索引,用浮点数计算并保存u/v的值。用sum保存子区间数字的和,l表示子区间的长度,sum/l可以得到子区间的平均值,用该平均值与u/v的值比对。相等的话,符合条件的子区间数量加一。


四、代码

public static int solution(int n, int u, int v, int[] arr) {
    int l;
    double num=(double)u/(double)v;
    int result=0,sum=0;
    for(int i=0;i<n;i++){
        sum=0;
        l=0;
        for(int j=i;j<n;j++){
            sum+=arr[j];
            l++;
            if((double)sum/(double)l==num){
                result++;
            }
        }
    }
    return result;
}

五、代码详解

double num=(double)u/(double)v;

用num保存u/v的值

for(int i=0;i<n;i++){
    sum=0;
    l=0;
    for(int j=i;j<n;j++){
        sum+=arr[j];
        l++;
        if((double)sum/(double)l==num){
            result++;
        }
    }
}

该内部循环中,i是子区间的开头,j是子区间的具体索引,sum是子区间的和,l是子区间长度。子区间开头不变,长度变化。长度每变一次,都要重新计算该子区间的平均值,并与u/v的值比对。外部循环中,子区间开头变化,子区间的和和子区间长度重新为0.


六、图解

样例:

输入:n = 3 ,u = 2 ,v = 1 ,arr = [1, 2, 3] 

输出:10

u/v=2/1=2

i=0j=0j=1j=2
区间[1][1,2][1,2,3]
136
长度123
平均值11.52
i=1j=1j=2
区间[2][2,3]
25
长度12
平均值22.5
i=2j=2
区间[3]
3
长度1
平均值3

选择以下情况,能满足题目要求。

  • i=0,j=2
  • i=1,j=1

所以有两种情况符合连续的子区间,其平均值恰好等于 u/v,结果为2。