Java 数组子序列的最大可能平均值--需要有效的解决方案

Java 数组子序列的最大可能平均值--需要有效的解决方案,java,algorithm,Java,Algorithm,输入 输出:任何子数组的最大可能平均值 1: array size (1 to 10^5) 2: Number to take average (1 to 10^3) 3: elements in array (1 to 10^5) Non sorted, any order is possible 下面我已经给出了o(n^2)的解,但它不适用于大输入 Eg: 5 3 1 2 3 4 5 o/p = 5 5 4 1 2 3 4 5 o/p = 3 for first example seq

输入

输出:任何子数组的最大可能平均值

1: array size (1 to 10^5)
2: Number to take average (1 to 10^3)
3: elements in array (1 to 10^5) Non sorted, any order is possible
下面我已经给出了o(n^2)的解,但它不适用于大输入

Eg:
5 3
1 2 3 4 5
o/p = 5

5 4
1 2 3 4 5
o/p = 3

for first example seq will be sum[0,4]=15 and its average with 3 will be 5.
for second example seq will be sum[2,4]=12 and its average with 4 will be 3.
long max=0;
for(int m=0;m最大值)
{
最大值=总和/箱数;
}
}
}
}
系统输出打印项次(最大值);
其中,
people
是数组大小,
box
是平均数,
chocolateArray
是原始数组


请提供有效的解决方案。我本想通过
动态规划
,但创建10^5大小的二维数组会导致outofmemory问题。

由于所有数字都是正数,唯一有效的约束是整除性。所以问题是求最大子数组和,它可以被
m
整除,即框的数量

这可以通过创建一个累加和的数组,模
m
,然后找到两个数字相同的地方,尽可能地分开。由于最多有
m
个值,我们可以简单地存储每个可能剩余的最小和最大索引,然后取子数组和最大的索引。下面的代码就是这样做的

            long max = 0;
            for( int m = 0; m < people; m++ )
            {
                long sum = 0;
                for( int n = m; n < people; n++ )
                {
                    sum = sum + chocolateArray[n];
                    if( sum % boxes == 0 )
                    {
                        if( ( sum / boxes ) > max )
                        {
                            max = sum / boxes;
                        }
                    }
                }
            }
            System.out.println( max );
cumsum=int[people+1];
minPos=int[box];
maxPos=int[box];
数组。填充(minPos,-1);
数组填充(maxPos,-1);
int剩余=0;
对于(int i=0;i sum=0->avg=0
MinMaxPos[1]=(0,0)->总和=0->平均值=0
MinMaxPos[2]=(2,3)->总和=4->平均值=1
MinMaxPos[3]=(1,4)->总和=12->平均值=3

基于@justhalf的卓越解决方案。我们将能够使用单通道和单阵列来实现这一点

dp[boxes]
为长度
boxes
的数组,其中
dp[i]
将保存迄今为止具有
i=当前_sum%boxes的最小和

由于所有的数字都是正数,我们只能存储特定
余数的第一次出现,因为下一次出现该余数时,它将大于上一次的和

在每次迭代中,我们检查是否已经找到一个特定的
余数
。如果是,则我们用该余数的前一个和减去
当前的总和

否则,我们将更新剩余值的总和并移动

People = 5 Boxes = 4 Array = [1, 2, 3, 4, 5] Cumulative = [1, 3, 6, 10, 15] Residue = [1, 3, 2, 2, 3] MinMaxPos[0] = (-1, -1) -> sum = 0 -> avg = 0 MinMaxPos[1] = (0, 0) -> sum = 0 -> avg = 0 MinMaxPos[2] = (2, 3) -> sum = 4 -> avg = 1 MinMaxPos[3] = (1, 4) -> sum = 12 -> avg = 3
int-maxSubrayAverage(向量人,int框)
{
向量dp(框-1);
int max_sum=0,当前_sum=0;
dp[0]=0;//如果余数为0,则选择整个当前_和
for(int i=0;i//在第二种情况下,为什么只取[2,4]而不取[0,4]?你需要澄清这项任务。我想你是在寻找一个子数组,它的和可以被盒子数整除,你想要其中的最大值?这非常类似于最大子数组和问题,在整除性上有额外的限制。@justhalf是的,你可以说类似的,但我知道我们可以用o(n)来解决这适用于数组中有负数的情况,否则每次求和都将是最大值,直到最后一次。这里是all+ve nums@ShanuGupta,因为在第二种情况下,求和为[0,4]=15,它不能被4整除。我们不能通过这个和得到平均值。问题可以归结为找到最小前缀和或后缀和,或两者的组合,以得到正确的余数。棘手的部分是组合。是的,我们可以一次性计算最大平均值。不需要保留maxPos。好的!!是的,我们当然可以这样做。为了清晰起见,我将最小和最大位置放在+1
People = 5
Boxes = 4
Array = [1, 2, 3,  4,  5]
Cumulative = [1, 3, 6, 10, 15]
Residue = [1, 3, 2, 2, 3]
MinMaxPos[0] = (-1, -1) -> sum = 0 -> avg = 0
MinMaxPos[1] = (0, 0) -> sum = 0 -> avg = 0
MinMaxPos[2] = (2, 3) -> sum = 4 -> avg = 1
MinMaxPos[3] = (1, 4) -> sum = 12 -> avg = 3
int maxSubArrayAverage(vector<int> people, int boxes)
{
    vector<int> dp(boxes, -1);
    int max_sum = 0, current_sum = 0;
    dp[0] = 0; // if residue is 0 entire current_sum is the choice
    for(int i=0; i < people.size(); ++i)
    {
        current_sum += people[i];
        int residue = current_sum % boxes;

        if(dp[residue] == -1) // update for the first time
        {
            dp[residue] = current_sum;
        }
        else
        {
            max_sum= max(max_sum, current_sum - dp[residue]);
            // cout << i << ' ' << current_sum << ' ' << residue << ' ' << max_average << endl;
        }
    }
    // copy(dp.begin(), dp.end(), ostream_iterator<int>(cout, " "));
    // cout << endl;
    return max_sum/boxes;
}