leetcode-152-线性DP-乘积最大子数组

题目

1.png

解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 动态规划
class Solution {
public:
tuple<int, int> m_min_max(int a, int b, int c){
int m_min = min(a, min(b, c));
int m_max = max(a, max(b, c));
return make_tuple(m_min, m_max);
}

int maxProduct(vector<int>& nums) {
int n = nums.size();
if(n == 0) return 0;
if(n == 1) return nums[0];

// dp[i][0], dp[i][1] 表示以第i个元素结尾的子序列的最大子序乘积的最小与最大值
vector<vector<int>> dp(n, vector<int>(2));
dp[0][0] = nums[0];
dp[0][1] = nums[0];

int res = dp[0][1];

for(int i = 1; i < n; ++i){
tie(dp[i][0], dp[i][1]) = m_min_max(dp[i-1][0] * nums[i],
dp[i-1][1] * nums[i], nums[i]);
if(dp[i][1] > res) res = dp[i][1];
}

return res;
}
};

// 动态规划,优化空间复杂度
class Solution {
public:
tuple<int, int> m_min_max(int a, int b, int c){
int m_min = min(a, min(b, c));
int m_max = max(a, max(b, c));
return make_tuple(m_min, m_max);
}

int maxProduct(vector<int>& nums) {
int n = nums.size();
if(n == 0) return 0;
if(n == 1) return nums[0];

int i_min = nums[0]; // 保存第i个元素结尾的连续子序列的最小乘积
int i_max = nums[0]; // 保存第i个元素结尾的连续子序列的最大乘积

int res = i_max;

for(int i = 1; i < n; ++i){
tie(i_min, i_max) = m_min_max(i_min*nums[i], i_max*nums[i], nums[i]);
if(i_max > res) res = i_max;
}

return res;
}
};