输入
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
输出:任何子阵列的最大平均值。
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.
我已经给出了o(n ^ 2)的解决方案,但它不适用于大输入。
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 );
其中people
是数组大小,boxes
是平均数,chocolateArray
是原始数组。
请提供有效的解决方案。我想通过dynamic programming
接受它,但是创建10 ^ 5大小的二维数组导致了内存问题。
答案 0 :(得分:2)
由于所有数字都是正数,唯一有效的约束是可分性。所以问题是要求最大的子阵列总和可以被m
整除,即盒子的数量。
这可以通过创建一个累积和的数组,模m
,然后找到两个具有相同数字的地方,尽可能远。由于最多有m
个值,我们可以简单地存储每个可能残差的最小和最大索引,然后选择具有最大子阵列总和的那个。下面的代码就是这样。
cumsum = int[people+1];
minPos = int[boxes];
maxPos = int[boxes];
Arrays.fill(minPos, -1);
Arrays.fill(maxPos, -1);
int residue = 0;
for(int i=0; i<people; i++){
cumsum[i+1] = cumsum[i] + chocolateArray[i]; // For simplicity the array length is 1 longer
residue = cumsum[i+1] % boxes;
if(minPos[residue] == -1) minPos[residue] = i;
maxPos[residue] = i;
}
int max = 0;
for(int i=0; i<boxes; i++){
int sum = cumsum[maxPos[i]+1] - cumsum[minPos[i]+1];
if(sum > max){
max = sum;
}
}
System.out.println(max/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
答案 1 :(得分:2)
立足于@ justhalf的精彩解决方案。我们将能够使用单次传递和仅一个数组
来完成此操作让dp[boxes]
成为长度为boxes
的数组,其中dp[i]
将保留到目前为止的最小总和i = current_sum % boxes
由于所有数字都是正数,我们只能存储特定residue
的第一次出现,因为下一次出现这个残差时,它将大于先前的总和。< / p>
在每次迭代时,我们都会检查是否已找到特定的residue
。如果是,那么我们用前一个残差的总和减去current_sum
。
否则我们更新残留物的总和并移动。
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;
}