53. 最大子序和与152. 乘积最大子数组
这两道题有相似之处,所以放在了一起记录
题目
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
思路
可以用动态规划来做,设数组元素f[i]表示包含第i个元素的最大和的连续子数组,那么转移方程是
f
[
i
]
=
m
a
x
(
f
[
i
−
1
]
+
A
[
i
]
,
A
[
i
]
)
f[i] = max(f[i-1]+A[i],A[i])
f[i]=max(f[i−1]+A[i],A[i])
代码
public int maxSubArray(int[] nums) {
int n = nums.length;
if(n==0){
return 0;
}
int f[] = new int [n];
f[0] = nums[0];
int m = Math.max(f[0],Integer.MIN_VALUE);
for(int i=1;i<n;i++){
f[i]= nums[i];
f[i] = Math.max(f[i]+f[i-1],f[i]);
if(m<f[i]){
m = f[i];
}
}
return m;
}
题目
给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
思路
和上面的题目类似,定义数组f[i],表示以第i个数结尾的乘积最大的连续子数组,那么很容易会使用上面的转移方程进行解决。但是这样是不对的
因为上面的问题是和,而这个问题是乘积,会出现负负得正的情况(负负得正可能比两个正数的乘积大),因此,还需要定义一个数组d[i]表示以第i个数结尾的乘积最小的连续子数组,状态转移方程可以写为:
f
[
i
]
=
m
a
x
(
d
[
i
−
1
]
∗
A
[
i
]
,
f
[
i
−
1
]
∗
A
[
i
]
,
A
[
i
]
)
f[i] = max(d[i-1]*A[i],f[i-1]*A[i],A[i])
f[i]=max(d[i−1]∗A[i],f[i−1]∗A[i],A[i])
d
[
i
]
=
m
i
n
(
d
[
i
−
1
]
∗
A
[
i
]
,
f
[
i
−
1
]
∗
A
[
i
]
,
A
[
i
]
)
d[i] = min(d[i-1]*A[i],f[i-1]*A[i],A[i])
d[i]=min(d[i−1]∗A[i],f[i−1]∗A[i],A[i])
代码
public int maxProduct(int[] nums) {
int n = nums.length;
int f[] = new int[n+1];
int d[] = new int[n+1];
int r = Integer.MIN_VALUE;
for(int i=1;i<=n;i++){
if(i==1)
{
f[i] = nums[i-1];
d[i]= nums[i-1];
}else{
f[i] = Math.max(nums[i-1],f[i-1]*nums[i-1]);
f[i] = Math.max(f[i],d[i-1]*nums[i-1]);
d[i] = Math.min(nums[i-1],f[i-1]*nums[i-1]);
d[i] = Math.min(d[i],d[i-1]*nums[i-1]);
}
r = Math.max(r,f[i]);
}
return r;
}
当然,上面代码可以继续优化,将空间优化到O(1),代码如下,优化思路很简单
public int maxProduct(int[] nums) {
int n = nums.length;
int f = 0;
int d = 0;
int r = Integer.MIN_VALUE;
for(int i=1;i<=n;i++){
if(i==1)
{
f = nums[i-1];
d= nums[i-1];
}else{
int tf = f;
int td = d;
f= Math.max(nums[i-1],tf*nums[i-1]);
f = Math.max(f,td*nums[i-1]);
d = Math.min(nums[i-1],td*nums[i-1]);
d = Math.min(d,tf*nums[i-1]);
}
// System.out.println(f+" "+nums[i-1]+" "+d);
r = Math.max(r,f);
}
return r;
}