@@ -56,7 +56,23 @@ coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167</pre>
56
56
57
57
<!-- solution:start -->
58
58
59
- ### 方法一
59
+ ### 方法一:动态规划
60
+
61
+ 我们记数组 $nums$ 的长度为 $n$。根据题目描述,我们可以在数组 $nums$ 的左右两端各添加一个 $1$,记为 $arr$。
62
+
63
+ 然后,我们定义 $f[ i] [ j ] $ 表示戳破区间 $[ i, j] $ 内的所有气球能得到的最多硬币数,那么答案即为 $f[ 0] [ n+1 ] $。
64
+
65
+ 对于 $f[ i] [ j ] $,我们枚举区间 $[ i, j] $ 内的所有位置 $k$,假设 $k$ 是最后一个戳破的气球,那么我们可以得到如下状态转移方程:
66
+
67
+ $$
68
+ f[i][j] = \max(f[i][j], f[i][k] + f[k][j] + arr[i] \times arr[k] \times arr[j])
69
+ $$
70
+
71
+ 在实现上,由于 $f[ i] [ j ] $ 的状态转移方程中涉及到 $f[ i] [ k ] $ 和 $f[ k] [ j ] $,其中 $i < k < j$,因此我们需要从大到小地遍历 $i$,从小到大地遍历 $j$,这样才能保证当计算 $f[ i] [ j ] $ 时 $f[ i] [ k ] $ 和 $f[ k] [ j ] $ 已经被计算出来。
72
+
73
+ 最后,我们返回 $f[ 0] [ n+1 ] $ 即可。
74
+
75
+ 时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组 $nums$ 的长度。
60
76
61
77
<!-- tabs:start -->
62
78
@@ -65,40 +81,35 @@ coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167</pre>
65
81
``` python
66
82
class Solution :
67
83
def maxCoins (self , nums : List[int ]) -> int :
68
- nums = [1 ] + nums + [1 ]
69
84
n = len (nums)
70
- dp = [[ 0 ] * n for _ in range (n) ]
71
- for l in range (2 , n):
72
- for i in range (n - l ):
73
- j = i + l
85
+ arr = [1 ] + nums + [ 1 ]
86
+ f = [[ 0 ] * (n + 2 ) for _ in range (n + 2 )]
87
+ for i in range (n - 1 , - 1 , - 1 ):
88
+ for j in range (i + 2 , n + 2 ):
74
89
for k in range (i + 1 , j):
75
- dp[i][j] = max (
76
- dp[i][j], dp[i][k] + dp[k][j] + nums[i] * nums[k] * nums[j]
77
- )
78
- return dp[0 ][- 1 ]
90
+ f[i][j] = max (f[i][j], f[i][k] + f[k][j] + arr[i] * arr[k] * arr[j])
91
+ return f[0 ][- 1 ]
79
92
```
80
93
81
94
#### Java
82
95
83
96
``` java
84
97
class Solution {
85
98
public int maxCoins (int [] nums ) {
86
- int [] vals = new int [nums. length + 2 ];
87
- vals[0 ] = 1 ;
88
- vals[vals. length - 1 ] = 1 ;
89
- System . arraycopy(nums, 0 , vals, 1 , nums. length);
90
- int n = vals. length;
91
- int [][] dp = new int [n][n];
92
- for (int l = 2 ; l < n; ++ l) {
93
- for (int i = 0 ; i + l < n; ++ i) {
94
- int j = i + l;
95
- for (int k = i + 1 ; k < j; ++ k) {
96
- dp[i][j]
97
- = Math . max(dp[i][j], dp[i][k] + dp[k][j] + vals[i] * vals[k] * vals[j]);
99
+ int n = nums. length;
100
+ int [] arr = new int [n + 2 ];
101
+ arr[0 ] = 1 ;
102
+ arr[n + 1 ] = 1 ;
103
+ System . arraycopy(nums, 0 , arr, 1 , n);
104
+ int [][] f = new int [n + 2 ][n + 2 ];
105
+ for (int i = n - 1 ; i >= 0 ; i-- ) {
106
+ for (int j = i + 2 ; j <= n + 1 ; j++ ) {
107
+ for (int k = i + 1 ; k < j; k++ ) {
108
+ f[i][j] = Math . max(f[i][j], f[i][k] + f[k][j] + arr[i] * arr[k] * arr[j]);
98
109
}
99
110
}
100
111
}
101
- return dp [0 ][n - 1 ];
112
+ return f [0 ][n + 1 ];
102
113
}
103
114
}
104
115
```
@@ -109,19 +120,21 @@ class Solution {
109
120
class Solution {
110
121
public:
111
122
int maxCoins(vector<int >& nums) {
112
- nums.insert(nums.begin(), 1);
113
- nums.push_back(1);
114
123
int n = nums.size();
115
- vector<vector<int >> dp(n, vector<int >(n));
116
- for (int l = 2; l < n; ++l) {
117
- for (int i = 0; i + l < n; ++i) {
118
- int j = i + l;
124
+ vector<int > arr(n + 2, 1);
125
+ for (int i = 0; i < n; ++i) {
126
+ arr[ i + 1] = nums[ i] ;
127
+ }
128
+
129
+ vector<vector<int>> f(n + 2, vector<int>(n + 2, 0));
130
+ for (int i = n - 1; i >= 0; --i) {
131
+ for (int j = i + 2; j <= n + 1; ++j) {
119
132
for (int k = i + 1; k < j; ++k) {
120
- dp [ i] [ j ] = max(dp [ i] [ j ] , dp [ i] [ k ] + dp [ k] [ j ] + nums [ i] * nums [ k] * nums [ j] );
133
+ f [i][j] = max(f [i][j], f [i][k] + f [k][j] + arr [i] * arr [k] * arr [j]);
121
134
}
122
135
}
123
136
}
124
- return dp [ 0] [ n - 1 ] ;
137
+ return f [0 ][n + 1 ];
125
138
}
126
139
};
127
140
```
@@ -130,44 +143,72 @@ public:
130
143
131
144
``` go
132
145
func maxCoins (nums []int ) int {
133
- vals := make([]int, len(nums)+2)
134
- for i := 0; i < len(nums); i++ {
135
- vals[i+1] = nums[i]
136
- }
137
- n := len(vals)
138
- vals[0], vals[n-1] = 1, 1
139
- dp := make([][]int, n)
140
- for i := 0; i < n; i++ {
141
- dp[i] = make([]int, n)
142
- }
143
- for l := 2; l < n; l++ {
144
- for i := 0; i+l < n; i++ {
145
- j := i + l
146
- for k := i + 1; k < j; k++ {
147
- dp[i][j] = max(dp[i][j], dp[i][k]+dp[k][j]+vals[i]*vals[k]*vals[j])
148
- }
149
- }
150
- }
151
- return dp[0][n-1]
146
+ n := len (nums)
147
+ arr := make ([]int , n+2 )
148
+ arr[0 ] = 1
149
+ arr[n+1 ] = 1
150
+ copy (arr[1 :], nums)
151
+
152
+ f := make ([][]int , n+2 )
153
+ for i := range f {
154
+ f[i] = make ([]int , n+2 )
155
+ }
156
+
157
+ for i := n - 1 ; i >= 0 ; i-- {
158
+ for j := i + 2 ; j <= n+1 ; j++ {
159
+ for k := i + 1 ; k < j; k++ {
160
+ f[i][j] = max (f[i][j], f[i][k] + f[k][j] + arr[i]*arr[k]*arr[j])
161
+ }
162
+ }
163
+ }
164
+
165
+ return f[0 ][n+1 ]
152
166
}
153
167
```
154
168
155
169
#### TypeScript
156
170
157
171
``` ts
158
172
function maxCoins(nums : number []): number {
159
- let n = nums .length ;
160
- let dp = Array .from ({ length: n + 1 }, v => new Array (n + 2 ).fill (0 ));
161
- nums .unshift (1 );
162
- nums .push (1 );
163
- for (let i = n - 1 ; i >= 0 ; -- i ) {
164
- for (let j = i + 2 ; j < n + 2 ; ++ j ) {
165
- for (let k = i + 1 ; k < j ; ++ k ) {
166
- dp [i ][j ] = Math .max (nums [i ] * nums [k ] * nums [j ] + dp [i ][k ] + dp [k ][j ], dp [i ][j ]);
173
+ const n = nums .length ;
174
+ const arr = Array (n + 2 ).fill (1 );
175
+ for (let i = 0 ; i < n ; i ++ ) {
176
+ arr [i + 1 ] = nums [i ];
177
+ }
178
+
179
+ const f: number [][] = Array .from ({ length: n + 2 }, () => Array (n + 2 ).fill (0 ));
180
+ for (let i = n - 1 ; i >= 0 ; i -- ) {
181
+ for (let j = i + 2 ; j <= n + 1 ; j ++ ) {
182
+ for (let k = i + 1 ; k < j ; k ++ ) {
183
+ f [i ][j ] = Math .max (f [i ][j ], f [i ][k ] + f [k ][j ] + arr [i ] * arr [k ] * arr [j ]);
184
+ }
185
+ }
186
+ }
187
+ return f [0 ][n + 1 ];
188
+ }
189
+ ```
190
+
191
+ #### Rust
192
+
193
+ ``` rust
194
+ impl Solution {
195
+ pub fn max_coins (nums : Vec <i32 >) -> i32 {
196
+ let n = nums . len ();
197
+ let mut arr = vec! [1 ; n + 2 ];
198
+ for i in 0 .. n {
199
+ arr [i + 1 ] = nums [i ];
200
+ }
201
+
202
+ let mut f = vec! [vec! [0 ; n + 2 ]; n + 2 ];
203
+ for i in (0 .. n ). rev () {
204
+ for j in i + 2 .. n + 2 {
205
+ for k in i + 1 .. j {
206
+ f [i ][j ] = f [i ][j ]. max (f [i ][k ] + f [k ][j ] + arr [i ] * arr [k ] * arr [j ]);
207
+ }
167
208
}
168
209
}
210
+ f [0 ][n + 1 ]
169
211
}
170
- return dp [0 ][n + 1 ];
171
212
}
172
213
```
173
214
0 commit comments