|
| 1 | +--- |
| 2 | +comments: true |
| 3 | +difficulty: 中等 |
| 4 | +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README.md |
| 5 | +--- |
| 6 | + |
| 7 | +<!-- problem:start --> |
| 8 | + |
| 9 | +# [3205. Maximum Array Hopping Score I 🔒](https://leetcode.cn/problems/maximum-array-hopping-score-i) |
| 10 | + |
| 11 | +[English Version](/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README_EN.md) |
| 12 | + |
| 13 | +## 题目描述 |
| 14 | + |
| 15 | +<!-- description:start --> |
| 16 | + |
| 17 | +<p>Given an array <code>nums</code>, you have to get the <strong>maximum</strong> score starting from index 0 and <strong>hopping</strong> until you reach the last element of the array.</p> |
| 18 | + |
| 19 | +<p>In each <strong>hop</strong>, you can jump from index <code>i</code> to an index <code>j > i</code>, and you get a <strong>score</strong> of <code>(j - i) * nums[j]</code>.</p> |
| 20 | + |
| 21 | +<p>Return the <em>maximum score</em> you can get.</p> |
| 22 | + |
| 23 | +<p> </p> |
| 24 | +<p><strong class="example">Example 1:</strong></p> |
| 25 | + |
| 26 | +<div class="example-block"> |
| 27 | +<p><strong>Input:</strong> <span class="example-io">nums = [1,5,8]</span></p> |
| 28 | + |
| 29 | +<p><strong>Output:</strong> <span class="example-io">16</span></p> |
| 30 | + |
| 31 | +<p><strong>Explanation:</strong></p> |
| 32 | + |
| 33 | +<p>There are two possible ways to reach the last element:</p> |
| 34 | + |
| 35 | +<ul> |
| 36 | + <li><code>0 -> 1 -> 2</code> with a score of <code>(1 - 0) * 5 + (2 - 1) * 8 = 13</code>.</li> |
| 37 | + <li><code>0 -> 2</code> with a score of <code>(2 - 0) * 8 = 16</code>.</li> |
| 38 | +</ul> |
| 39 | +</div> |
| 40 | + |
| 41 | +<p><strong class="example">Example 2:</strong></p> |
| 42 | + |
| 43 | +<div class="example-block"> |
| 44 | +<p><strong>Input:</strong> <span class="example-io">nums = [4,5,2,8,9,1,3]</span></p> |
| 45 | + |
| 46 | +<p><strong>Output:</strong> <span class="example-io">42</span></p> |
| 47 | + |
| 48 | +<p><strong>Explanation:</strong></p> |
| 49 | + |
| 50 | +<p>We can do the hopping <code>0 -> 4 -> 6</code> with a score of <code>(4 - 0) * 9 + (6 - 4) * 3 = 42</code>.</p> |
| 51 | +</div> |
| 52 | + |
| 53 | +<p> </p> |
| 54 | +<p><strong>Constraints:</strong></p> |
| 55 | + |
| 56 | +<ul> |
| 57 | + <li><code>2 <= nums.length <= 10<sup>3</sup></code></li> |
| 58 | + <li><code>1 <= nums[i] <= 10<sup>5</sup></code></li> |
| 59 | +</ul> |
| 60 | + |
| 61 | +<!-- description:end --> |
| 62 | + |
| 63 | +## 解法 |
| 64 | + |
| 65 | +<!-- solution:start --> |
| 66 | + |
| 67 | +### 方法一:记忆化搜索 |
| 68 | + |
| 69 | +我们设计一个函数 $\text{dfs}(i)$,表示从下标 $i$ 出发,能够获得的最大分数。那么答案就是 $\text{dfs}(0)$。 |
| 70 | + |
| 71 | +函数 $\text{dfs}(i)$ 的执行过程如下: |
| 72 | + |
| 73 | +我们枚举下一个跳跃的位置 $j$,那么从下标 $i$ 出发,能够获得的分数就是 $(j - i) \times \text{nums}[j]$,加上从下标 $j$ 出发,能够获得的最大分数,总分数就是 $(j - i) \times \text{nums}[j] + \text{dfs}(j)$。我们枚举所有的 $j$,取分数的最大值即可。 |
| 74 | + |
| 75 | +为了避免重复计算,我们使用记忆化搜索的方法,将已经计算过的 $\text{dfs}(i)$ 的值保存起来,下次直接返回即可。 |
| 76 | + |
| 77 | +时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。 |
| 78 | + |
| 79 | +<!-- tabs:start --> |
| 80 | + |
| 81 | +#### Python3 |
| 82 | + |
| 83 | +```python |
| 84 | +class Solution: |
| 85 | + def maxScore(self, nums: List[int]) -> int: |
| 86 | + @cache |
| 87 | + def dfs(i: int) -> int: |
| 88 | + return max( |
| 89 | + [(j - i) * nums[j] + dfs(j) for j in range(i + 1, len(nums))] or [0] |
| 90 | + ) |
| 91 | + |
| 92 | + return dfs(0) |
| 93 | +``` |
| 94 | + |
| 95 | +#### Java |
| 96 | + |
| 97 | +```java |
| 98 | +class Solution { |
| 99 | + private Integer[] f; |
| 100 | + private int[] nums; |
| 101 | + private int n; |
| 102 | + |
| 103 | + public int maxScore(int[] nums) { |
| 104 | + n = nums.length; |
| 105 | + f = new Integer[n]; |
| 106 | + this.nums = nums; |
| 107 | + return dfs(0); |
| 108 | + } |
| 109 | + |
| 110 | + private int dfs(int i) { |
| 111 | + if (f[i] != null) { |
| 112 | + return f[i]; |
| 113 | + } |
| 114 | + f[i] = 0; |
| 115 | + for (int j = i + 1; j < n; ++j) { |
| 116 | + f[i] = Math.max(f[i], (j - i) * nums[j] + dfs(j)); |
| 117 | + } |
| 118 | + return f[i]; |
| 119 | + } |
| 120 | +} |
| 121 | +``` |
| 122 | + |
| 123 | +#### C++ |
| 124 | + |
| 125 | +```cpp |
| 126 | +class Solution { |
| 127 | +public: |
| 128 | + int maxScore(vector<int>& nums) { |
| 129 | + int n = nums.size(); |
| 130 | + vector<int> f(n); |
| 131 | + auto dfs = [&](auto&& dfs, int i) -> int { |
| 132 | + if (f[i]) { |
| 133 | + return f[i]; |
| 134 | + } |
| 135 | + for (int j = i + 1; j < n; ++j) { |
| 136 | + f[i] = max(f[i], (j - i) * nums[j] + dfs(dfs, j)); |
| 137 | + } |
| 138 | + return f[i]; |
| 139 | + }; |
| 140 | + return dfs(dfs, 0); |
| 141 | + } |
| 142 | +}; |
| 143 | +``` |
| 144 | +
|
| 145 | +#### Go |
| 146 | +
|
| 147 | +```go |
| 148 | +func maxScore(nums []int) int { |
| 149 | + n := len(nums) |
| 150 | + f := make([]int, n) |
| 151 | + var dfs func(int) int |
| 152 | + dfs = func(i int) int { |
| 153 | + if f[i] > 0 { |
| 154 | + return f[i] |
| 155 | + } |
| 156 | + for j := i + 1; j < n; j++ { |
| 157 | + f[i] = max(f[i], (j-i)*nums[j]+dfs(j)) |
| 158 | + } |
| 159 | + return f[i] |
| 160 | + } |
| 161 | + return dfs(0) |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +#### TypeScript |
| 166 | + |
| 167 | +```ts |
| 168 | +function maxScore(nums: number[]): number { |
| 169 | + const n = nums.length; |
| 170 | + const f: number[] = Array(n).fill(0); |
| 171 | + const dfs = (i: number): number => { |
| 172 | + if (f[i]) { |
| 173 | + return f[i]; |
| 174 | + } |
| 175 | + for (let j = i + 1; j < n; ++j) { |
| 176 | + f[i] = Math.max(f[i], (j - i) * nums[j] + dfs(j)); |
| 177 | + } |
| 178 | + return f[i]; |
| 179 | + }; |
| 180 | + return dfs(0); |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +<!-- tabs:end --> |
| 185 | + |
| 186 | +<!-- solution:end --> |
| 187 | + |
| 188 | +<!-- solution:start --> |
| 189 | + |
| 190 | +### 方法二:动态规划 |
| 191 | + |
| 192 | +我们可以将方法一中的记忆化搜索转换为动态规划。 |
| 193 | + |
| 194 | +定义 $f[j]$ 表示从下标 $0$ 出发,到下标 $j$ 结束,能够获得的最大分数。那么答案就是 $f[n - 1]$。 |
| 195 | + |
| 196 | +状态转移方程为: |
| 197 | + |
| 198 | +$$ |
| 199 | +f[j] = \max_{0 \leq i < j} \{ f[i] + (j - i) \times \text{nums}[j] \} |
| 200 | +$$ |
| 201 | + |
| 202 | +时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。 |
| 203 | + |
| 204 | +<!-- tabs:start --> |
| 205 | + |
| 206 | +#### Python3 |
| 207 | + |
| 208 | +```python |
| 209 | +class Solution: |
| 210 | + def maxScore(self, nums: List[int]) -> int: |
| 211 | + n = len(nums) |
| 212 | + f = [0] * n |
| 213 | + for j in range(1, n): |
| 214 | + for i in range(j): |
| 215 | + f[j] = max(f[j], f[i] + (j - i) * nums[j]) |
| 216 | + return f[n - 1] |
| 217 | +``` |
| 218 | + |
| 219 | +#### Java |
| 220 | + |
| 221 | +```java |
| 222 | +class Solution { |
| 223 | + public int maxScore(int[] nums) { |
| 224 | + int n = nums.length; |
| 225 | + int[] f = new int[n]; |
| 226 | + for (int j = 1; j < n; ++j) { |
| 227 | + for (int i = 0; i < j; ++i) { |
| 228 | + f[j] = Math.max(f[j], f[i] + (j - i) * nums[j]); |
| 229 | + } |
| 230 | + } |
| 231 | + return f[n - 1]; |
| 232 | + } |
| 233 | +} |
| 234 | +``` |
| 235 | + |
| 236 | +#### C++ |
| 237 | + |
| 238 | +```cpp |
| 239 | +class Solution { |
| 240 | +public: |
| 241 | + int maxScore(vector<int>& nums) { |
| 242 | + int n = nums.size(); |
| 243 | + vector<int> f(n); |
| 244 | + for (int j = 1; j < n; ++j) { |
| 245 | + for (int i = 0; i < j; ++i) { |
| 246 | + f[j] = max(f[j], f[i] + (j - i) * nums[j]); |
| 247 | + } |
| 248 | + } |
| 249 | + return f[n - 1]; |
| 250 | + } |
| 251 | +}; |
| 252 | +``` |
| 253 | +
|
| 254 | +#### Go |
| 255 | +
|
| 256 | +```go |
| 257 | +func maxScore(nums []int) int { |
| 258 | + n := len(nums) |
| 259 | + f := make([]int, n) |
| 260 | + for j := 1; j < n; j++ { |
| 261 | + for i := 0; i < j; i++ { |
| 262 | + f[j] = max(f[j], f[i]+(j-i)*nums[j]) |
| 263 | + } |
| 264 | + } |
| 265 | + return f[n-1] |
| 266 | +} |
| 267 | +``` |
| 268 | + |
| 269 | +#### TypeScript |
| 270 | + |
| 271 | +```ts |
| 272 | +function maxScore(nums: number[]): number { |
| 273 | + const n = nums.length; |
| 274 | + const f: number[] = Array(n).fill(0); |
| 275 | + for (let j = 1; j < n; ++j) { |
| 276 | + for (let i = 0; i < j; ++i) { |
| 277 | + f[j] = Math.max(f[j], f[i] + (j - i) * nums[j]); |
| 278 | + } |
| 279 | + } |
| 280 | + return f[n - 1]; |
| 281 | +} |
| 282 | +``` |
| 283 | + |
| 284 | +<!-- tabs:end --> |
| 285 | + |
| 286 | +<!-- solution:end --> |
| 287 | + |
| 288 | +<!-- problem:end --> |
0 commit comments