问题描述
给你两个长度分别 n
和 m
的整数数组 nums
和 multipliers
,其中 n >= m
,数组下标 从 1 开始 计数。
初始时,你的分数为 0
。你需要执行恰好 m
步操作。在第 i
步操作(从 1 开始 计数)中,需要:
- 选择数组
nums
开头处或者末尾处 的整数 x
。
- 你获得
multipliers[i] * x
分,并累加到你的分数中。
- 将
x
从数组 nums
中移除。
在执行 m
步操作后,返回 最大 分数。
示例 1:
输入:nums = [1,2,3], multipliers = [3,2,1]
输出:14
解释:一种最优解决方案如下:
- 选择末尾处的整数 3 ,[1,2,3] ,得 3 * 3 = 9 分,累加到分数中。
- 选择末尾处的整数 2 ,[1,2] ,得 2 * 2 = 4 分,累加到分数中。
- 选择末尾处的整数 1 ,[1] ,得 1 * 1 = 1 分,累加到分数中。
总分数为 9 + 4 + 1 = 14 。
示例 2:
输入:nums = [-5,-3,-3,-2,7,1], multipliers = [-10,-5,3,4,6]
输出:102
解释:一种最优解决方案如下:
- 选择开头处的整数 -5 ,[-5,-3,-3,-2,7,1] ,得 -5 * -10 = 50 分,累加到分数中。
- 选择开头处的整数 -3 ,[-3,-3,-2,7,1] ,得 -3 * -5 = 15 分,累加到分数中。
- 选择开头处的整数 -3 ,[-3,-2,7,1] ,得 -3 * 3 = -9 分,累加到分数中。
- 选择末尾处的整数 1 ,[-2,7,1] ,得 1 * 4 = 4 分,累加到分数中。
- 选择末尾处的整数 7 ,[-2,7] ,得 7 * 6 = 42 分,累加到分数中。
总分数为 50 + 15 - 9 + 4 + 42 = 102 。
提示:
n == nums.length
m == multipliers.length
1 <= m <= 103
m <= n <= 105
-1000 <= nums[i], multipliers[i] <= 1000
解题思路
用 \(\texttt{dp}[i][j]\) 表示左边取了 \(i\) 个数,右边取了 \(j\) 个数能够达到的最大值,那么有:
\[
\begin{aligned}
\texttt{l}&=\texttt{nums}[i-1]\times\texttt{multipliers}[i+j-1]+\texttt{dp}[i-1][j] \\
\texttt{r}&=\texttt{nums}[n-j]\times\texttt{multipliers}[i+j-1]+\texttt{dp}[i][j-1] \\
\texttt{dp}[i][j]&=\max(l,r)
\end{aligned}
\]
然后最大值为 \(\texttt{dp}[i][m-i]\)。
方法一:记忆化搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | class Solution:
def maximumScore(self, nums: List[int], muls: List[int]) -> int:
n, m = len(nums), len(muls)
M = m + 1
INF = 2 * 10 ** 9
cache = [INF] * M * M
def dp(i: int, j: int) -> int:
q = i * M + j
if cache[q] != INF:
return cache[q]
k = i + j
if k == m:
cache[q] = 0
else:
cache[q] = max(nums[i] * muls[k] + dp(i + 1, j), nums[n - 1 - j] * muls[k] + dp(i, j + 1))
return cache[q]
return dp(0, 0)
|
调用 cache_clear() 的原因
1
2
3
4
5
6
7
8
9
10
11
12
13 | class Solution:
def maximumScore(self, nums: List[int], muls: List[int]) -> int:
n, m = len(nums), len(muls)
@cache
def dp(i: int, j: int, k: int) -> int:
if k == m:
return 0
return max(nums[i] * muls[k] + dp(i + 1, j, k + 1), nums[j] * muls[k] + dp(i, j - 1, k + 1))
ans = dp(0, n - 1, 0)
dp.cache_clear()
return ans
|
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 | class Solution {
public:
int maximumScore(vector<int>& nums, vector<int>& muls) {
int n = nums.size(), m = muls.size(), M = m + 1;
int INF = 2e9;
vector<int> cache(M * M, INF);
function<int(int, int)> dp = [&] (int i, int j) {
int q = i * M + j;
if (cache[q] != INF) {
return cache[q];
}
int k = i + j;
if (k == m) {
cache[q] = 0;
} else {
cache[q] = max(nums[i] * muls[k] + dp(i + 1, j), nums[n - 1 - j] * muls[k] + dp(i, j + 1));
}
return cache[q];
};
return dp(0, 0);
}
};
|
时间复杂度:\(\mathcal{O}(m^2)\)
空间复杂度:\(\mathcal{O}(m^2)\)
方法二:递推
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | class Solution:
def maximumScore(self, nums: List[int], muls: List[int]) -> int:
n, m = len(nums), len(muls)
dp = [[0] * (m + 1) for _ in range(m + 1)]
INF = -2 * 10 ** 9
for i in range(m + 1):
for j in range(m - i + 1):
if i or j:
l = r = INF
if i:
l = nums[i - 1] * muls[i + j - 1] + dp[i - 1][j]
if j:
r = nums[n - j] * muls[i + j - 1] + dp[i][j - 1]
dp[i][j] = max(l, r)
ans = INF
for i in range(m + 1):
ans = max(ans, dp[i][m - i])
return ans
|
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 | class Solution {
public:
int maximumScore(vector<int>& nums, vector<int>& muls) {
int n = nums.size(), m = muls.size();
vector<vector<int>> dp(m + 1, vector<int>(m + 1));
int INF = -2e9;
for (int i = 0; i <= m; ++i) {
for (int j = 0; i + j <= m; ++j) {
if (i || j) {
int l = INF, r = INF;
if (i) {
l = nums[i - 1] * muls[i + j - 1] + dp[i - 1][j];
}
if (j) {
r = nums[n - j] * muls[i + j - 1] + dp[i][j - 1];
}
dp[i][j] = max(l, r);
}
}
}
int ans = INF;
for (int i = 0; i <= m; ++i) {
ans = max(ans, dp[i][m - i]);
}
return ans;
}
};
|
时间复杂度:\(\mathcal{O}(m^2)\)
空间复杂度:\(\mathcal{O}(m^2)\)