给定一个数组序列, 需要求选出一个区间, 使得该区间是所有区间中经过如下计算的值最大的一个:
区间中的最小数 * 区间所有数的和最后程序输出经过计算后的最大值即可,不需要输出具体的区间。如给定序列 [6 2 1]则根据上述公式, 可得到所有可以选定各个区间的计算值:
[6] = 6 * 6 = 36;
[2] = 2 * 2 = 4;
[1] = 1 * 1 = 1;
[6,2] = 2 * 8 = 16;
[2,1] = 1 * 3 = 3;
[6, 2, 1] = 1 * 9 = 9;
从上述计算可见选定区间 [6] ,计算值为 36, 则程序输出为 36。
区间内的所有数字都在[0, 100]的范围内;
输入描述:
第一行输入数组序列长度n,第二行输入数组序列。 对于 50%的数据, 1 <= n <= 10000; 对于 100%的数据, 1 <= n <= 500000;
输出描述:
输出数组经过计算后的最大值。
输入例子1:
3 6 2 1
输出例子1:
36
解题思路:
对于序列a中开始于i结束于j的区间最小值*区间所有数和 = dpmin[i][j] * dpsum[i][j];
对于dpmin[i][j]:开始于i结束于j的区间最小值


对于dpsum[i][j]:开始于i结束于j的区间最小值


实现思路
创建2个int[a.length][a.length]的矩阵,分别计算dpmin[i][j],dpsum[i][j],然后遍历求积最大;
但是报错:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
(Java堆空间内存溢出)
为减小内存:只用dpminLast、dpminNow记录和更新dpmin
dpsumLast 、dpsumNow记录和更新dpsum
代码实现
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int len = in.nextInt();
int[] a = new int[len];
for (int i = 0; i < a.length; i++)
a[i] = in.nextInt();
// int[][] dpmin = new int[len][len];
int dpminLast = a[0],dpminNow = a[0];
int dpsumLast = a[0],dpsumNow = a[0];
int temp = dpminNow*dpsumNow;
for (int i = 0; i < a.length; i++) {
dpminLast = a[i];
dpsumLast = a[i];
if(temp < a[i]*a[i])
temp = a[i]*a[i];
for (int j = i + 1 ; j < a.length; j++) {
dpminNow = a[j] < dpminLast ? a[j] : dpminLast;
dpsumNow = a[j] + dpsumLast;
if(temp < dpminNow*dpsumNow)
temp = dpminNow*dpsumNow;
dpminLast = dpminNow;
dpsumLast = dpsumNow;
}
}
// for (int i = 0; i < a.length; i++) {
// dpmin[i][i] = a[i];
// for (int j = i + 1; j < a.length; j++) {
// dpmin[i][j] = a[j] < dpmin[i][j-1] ? a[j] : dpmin[i][j-1];
// }
// }
//
// int[][] dpsum = new int[len][len];
// for (int i = 0; i < a.length; i++) {
// dpsum[i][i] = a[i];
// for (int j = i + 1; j < a.length; j++) {
// dpsum[i][j] = a[j] + dpsum[i][j-1];
// }
// }
// int temp = dpmin[0][0]*dpsum[0][0];
// for (int i = 0; i < a.length; i++)
// for (int j = i; j < a.length; j++)
// if(temp < dpmin[i][j]*dpsum[i][j])
// temp = dpmin[i][j]*dpsum[i][j];
System.out.println(temp);
}
}但是只有70%的通过率!!!
本题能正确通过的思路是:按照y轴升序,x轴降序排序,然后从最后一个元素开始,始终与(y后者x)最大元素做对比,如果比最大元素大,就保存到栈中,然后把最大元素更新;如果小于最大元素,那么就查看下一个元素。

给定一个数组,要求选择一个区间,使区间内最小数乘以区间内所有数之和达到最大。对于序列[6, 2, 1],最大计算值区间为[6],计算值为36。问题在于解决此问题时出现Java堆空间内存溢出错误,通过优化算法降低内存使用,但仅有70%的测试用例通过。解决方案是按y轴升序、x轴降序排序,比较并更新最大元素。"
53229483,1432347,Sprint规划会议:理解与决策,"['敏捷开发', 'Scrum框架', '产品管理', '团队协作', '项目规划']
4119

被折叠的 条评论
为什么被折叠?



