题目链接
动态规划的典型题目,这道题实际上是最大连续子数组和的一个进阶版本。这道题的难点在于,这里要同时构建两个辅助数组。
f
(
n
)
f(n)
f(n)代表从区间
[
0
,
n
]
[0,n]
[0,n]内,以n为结尾的最大乘积。与之相对的,
g
(
n
)
g(n)
g(n)代表从区间
[
0
,
n
]
[0,n]
[0,n]内,以n为结尾的最小乘积
动态转移的方程是这样的
f
(
n
)
=
m
a
x
{
f
(
n
−
1
)
×
a
[
n
]
,
a
[
n
]
,
g
(
n
−
1
)
×
a
[
n
]
}
f(n)=max\{f(n-1)\times a[n],a[n],g(n-1)\times a[n]\}
f(n)=max{f(n−1)×a[n],a[n],g(n−1)×a[n]}
g
(
n
)
=
m
a
x
{
f
(
n
−
1
)
×
a
[
n
]
,
a
[
n
]
,
g
(
n
−
1
)
×
a
[
n
]
}
g(n)=max\{f(n-1)\times a[n],a[n],g(n-1)\times a[n]\}
g(n)=max{f(n−1)×a[n],a[n],g(n−1)×a[n]}
这个算法实际上遍历一遍就能得出结果。虽然
f
(
n
)
f(n)
f(n)定义的是区间
[
0
,
n
]
[0,n]
[0,n]的值,但是算法会自动判断
a
[
n
]
a[n]
a[n]与左侧的值相乘数值会不会增加,从而选择截断或者是延续。
当算法运行完毕后,
f
(
n
)
f(n)
f(n)实际上代表一小段包括
a
[
n
]
a[n]
a[n]的子区间的乘积最大值。
class Solution {
int threemax(int a, int b, int c)
{
return max(a, max(b, c));
}
int threemin(int a, int b, int c)
{
return min(a, min(b, c));
}
public:
int maxProduct(vector<int>& nums) {
int size = nums.size();
if (size == 0)return 0;
vector<long long>nummax(size, 1);
vector<long long>nummin(size, 1);
nummax[0] = nummin[0] = nums[0];
for (int i = 1; i < size; i++)
{
nummax[i] = threemax(nummax[i - 1] * nums[i], nums[i], nummin[i - 1] * nums[i]);
nummin[i] = threemin(nummax[i - 1] * nums[i], nums[i], nummin[i - 1] * nums[i]);
}
long long ans = -0x3f3f3f3f;
for (int i = 0; i < size; i++)
{
ans = max(ans, nummax[i]);
}
return ans;
}
};