目录
题目
给定一个double类型的数组arr,其中的元素可正、可负、可0,返回子数组累乘的最大乘积。例如,arr=[-2.5, 4, 0, 3, 0.5, 8, -1],子数组[3, 0.5, 8]累乘可以获得最大的乘积12,所以返回12
[要求]
时间复杂度为O(N),空间复杂度为O(1)
输入描述:
第一行一个整数N。表示数组长度。 接下来一行N个浮点数表示数组内的数
输出描述:
输出一个浮点数表示答案,保留到小数点后两位
示例1
输入
7 -2.5 4 0 3 0.5 8 -1
输出
12.00
备注:
1 ≤ N ≤ Math.pow(10,5)
-100 ≤ arri ≤ 100
Math.pow(-10,22) ≤ 保证最后的答案 ≤ Math.pow(10,22)
错误的思路分析:
- 创建dp[n]一维数组
- 由于是子数组,所以dp[i]的含义是,以i结尾的子数组的最大值
- 初始化
- 如果数组长度=0,则返回1并退出
- 如果第一个数是负数,则dp[0]=1
- 如果是自然数,则dp[0]为该自然数数值
- 其余点:
- 如果当前数为0,则dp[i]=0
- 如果当前数为负数,
- 且dp[i-1]
- 否则dp[i] = arr[i]
- 如果当前数是正数
- 且dp[i-1]>0, dp[i] = dp[i-1]*arr[i]
- 否则d[i] = arr[i]
- 结果:
- dp中的最大值即为结果
错误原因:
不同于,加法,需要舍弃负数,这道题是子数组相乘。
这道题看起来很简单,实则暗藏杀机,如果就按照上述方法这样写
会发现dp会将隐藏的负数宝藏给丢弃掉,也许此时负数没什么用,但也许在不久的将来,负数成负数,摇身一变,变成了最大值
就比如这个例子
arr = { 10,10,10,-1,-20}
如果按照上述思路写,答案会是(-1*10)= 20 ,但是之前的dp[4]如果为-1000,此时答案可以为20000
改进后的思路:
- 创建dp[n][2]二维数组,
- dp[i][0]的含义是,以i结尾的子数组的最大值
- dp[i][1]的含义是,以i结尾的子数组的最小值
- 初始化
- 如果数组长度=0,则返回1并退出
- dp[i][0] = dp[i][1] = arr[i]
- 其余点:
- 如果当前数为0,则dp[i][0] = dp[i][1] = 0
- dp[i][0] = arr[i], arr[i]*dp[i-1][0], arr[i]*dp[i-1][1] 三者中的最小值
- dp[i][0] = arr[i], arr[i]*dp[i-1][0], arr[i]*dp[i-1][1] 三者中的最大值
- 结果:
- dp中的最大值即为结果
样例推导:
代码展示:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main{
public static void main(String[] args)throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
double [] arr = new double[n];
String[] str = reader.readLine().split(" ");
for(int i=0;i<n;i++){
arr[i] = Double.parseDouble(str[i]);
}
double [][] dp = new double[n][2];
dp[0][0] = dp[0][1] = arr[0];
double ans = 0;
for(int i=1;i<n;i++){
double p1 = arr[i];
double p2 = arr[i] * dp[i-1][0];
double p3 = arr[i] * dp[i-1][1];
dp[i][0] = Math.max(p1, Math.max(p2, p3));
ans = Math.max(ans, dp[i][0]);
dp[i][1] = Math.min(p1, Math.min(p2, p3));
}
System.out.printf("%.2f", ans);
}
}
空间压缩技巧:
import java.i.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main{
public static void main(String[] args)throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
double [] arr = new double[n];
String[] str = reader.readLine().split(" ");
for(int i=0;i<n;i++){
arr[i] = Double.parseDouble(str[i]);
}
double dp00;
double dp01;
dp00 = dp01 = arr[0];
double ans = 0;
double p1,p2,p3;
for(int i=1;i<n;i++){
p1 = arr[i];
p2 = arr[i] * dp00;
p3 = arr[i] * dp01;
dp00 = Math.max(p1, Math.max(p2, p3));
ans = Math.max(ans, dp00);
dp01 = Math.min(p1, Math.min(p2, p3));
}
System.out.printf("%.2f", ans);
}
}