@@ -53,15 +53,22 @@ tags:
53
53
54
54
### 方法一:动态规划
55
55
56
- 我们定义 $dp [ i] $ 表示正整数 $n$ 能获得的最大乘积,初始化 $dp [ 1] = 1$。答案即为 $dp [ n] $。
56
+ 我们定义 $f [ i] $ 表示正整数 $i$ 拆分后能获得的最大乘积,初始时 $f [ 1] = 1$。答案即为 $f [ n] $。
57
57
58
- 状态转移方程为:
58
+ 考虑 $i$ 最后拆分出的数字 $j$,其中 $j \in [ 1, i)$。对于 $i$ 拆分出的数字 $j$,有两种情况:
59
+
60
+ 1 . 将 $i$ 拆分成 $i - j$ 和 $j$ 的和,不继续拆分,此时乘积为 $(i - j) \times j$;
61
+ 2 . 将 $i$ 拆分成 $i - j$ 和 $j$ 的和,继续拆分,此时乘积为 $f[ i - j] \times j$。
62
+
63
+ 因此,我们可以得到状态转移方程:
59
64
60
65
$$
61
- dp [i] = max(dp [i], dp [i - j] \times j, (i - j) \times j) \quad (j \in [0, i))
66
+ f [i] = \ max(f [i], f [i - j] \times j, (i - j) \times j) \quad (j \in [0, i))
62
67
$$
63
68
64
- 时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为正整数 $n$。
69
+ 最后返回 $f[ n] $ 即可。
70
+
71
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为给定的正整数。
65
72
66
73
<!-- tabs:start -->
67
74
70
77
``` python
71
78
class Solution :
72
79
def integerBreak (self , n : int ) -> int :
73
- dp = [1 ] * (n + 1 )
80
+ f = [1 ] * (n + 1 )
74
81
for i in range (2 , n + 1 ):
75
82
for j in range (1 , i):
76
- dp [i] = max (dp [i], dp [i - j] * j, (i - j) * j)
77
- return dp [n]
83
+ f [i] = max (f [i], f [i - j] * j, (i - j) * j)
84
+ return f [n]
78
85
```
79
86
80
87
#### Java
81
88
82
89
``` java
83
90
class Solution {
84
91
public int integerBreak (int n ) {
85
- int [] dp = new int [n + 1 ];
86
- dp [1 ] = 1 ;
92
+ int [] f = new int [n + 1 ];
93
+ f [1 ] = 1 ;
87
94
for (int i = 2 ; i <= n; ++ i) {
88
95
for (int j = 1 ; j < i; ++ j) {
89
- dp [i] = Math . max(Math . max(dp [i], dp [i - j] * j), (i - j) * j);
96
+ f [i] = Math . max(Math . max(f [i], f [i - j] * j), (i - j) * j);
90
97
}
91
98
}
92
- return dp [n];
99
+ return f [n];
93
100
}
94
101
}
95
102
```
@@ -100,14 +107,14 @@ class Solution {
100
107
class Solution {
101
108
public:
102
109
int integerBreak(int n) {
103
- vector<int > dp (n + 1);
104
- dp [ 1] = 1;
110
+ vector<int > f (n + 1);
111
+ f [ 1] = 1;
105
112
for (int i = 2; i <= n; ++i) {
106
113
for (int j = 1; j < i; ++j) {
107
- dp [ i] = max(max(dp [ i] , dp [ i - j] * j) , (i - j) * j);
114
+ f [ i] = max({f [ i] , f [ i - j] * j, (i - j) * j} );
108
115
}
109
116
}
110
- return dp [ n] ;
117
+ return f [ n] ;
111
118
}
112
119
};
113
120
```
@@ -116,28 +123,28 @@ public:
116
123
117
124
```go
118
125
func integerBreak(n int) int {
119
- dp := make([]int, n+1)
120
- dp [1] = 1
126
+ f := make([]int, n+1)
127
+ f [1] = 1
121
128
for i := 2; i <= n; i++ {
122
129
for j := 1; j < i; j++ {
123
- dp [i] = max(max(dp [i], dp [i-j]*j), (i-j)*j)
130
+ f [i] = max(max(f [i], f [i-j]*j), (i-j)*j)
124
131
}
125
132
}
126
- return dp [n]
133
+ return f [n]
127
134
}
128
135
```
129
136
130
137
#### TypeScript
131
138
132
139
``` ts
133
140
function integerBreak(n : number ): number {
134
- let dp = new Array (n + 1 ).fill (1 );
141
+ const f = Array (n + 1 ).fill (1 );
135
142
for (let i = 3 ; i <= n ; i ++ ) {
136
143
for (let j = 1 ; j < i ; j ++ ) {
137
- dp [i ] = Math .max (dp [i ], j * (i - j ), j * dp [i - j ]);
144
+ f [i ] = Math .max (f [i ], j * (i - j ), j * f [i - j ]);
138
145
}
139
146
}
140
- return dp . pop () ;
147
+ return f [ n ] ;
141
148
}
142
149
```
143
150
@@ -146,24 +153,69 @@ function integerBreak(n: number): number {
146
153
``` rust
147
154
impl Solution {
148
155
pub fn integer_break (n : i32 ) -> i32 {
149
- if n < 4 {
150
- return n - 1 ;
156
+ let n = n as usize ;
157
+ let mut f = vec! [0 ; n + 1 ];
158
+ f [1 ] = 1 ;
159
+ for i in 2 ..= n {
160
+ for j in 1 .. i {
161
+ f [i ] = f [i ]. max (f [i - j ] * j ). max ((i - j ) * j );
162
+ }
163
+ }
164
+ f [n ] as i32
165
+ }
166
+ }
167
+ ```
168
+
169
+ #### JavaScript
170
+
171
+ ``` js
172
+ /**
173
+ * @param {number} n
174
+ * @return {number}
175
+ */
176
+ var integerBreak = function (n ) {
177
+ const f = Array (n + 1 ).fill (1 );
178
+ for (let i = 2 ; i <= n; ++ i) {
179
+ for (let j = 1 ; j < i; ++ j) {
180
+ f[i] = Math .max (f[i], f[i - j] * j, (i - j) * j);
181
+ }
182
+ }
183
+ return f[n];
184
+ };
185
+ ```
186
+
187
+ #### C#
188
+
189
+ ``` cs
190
+ public class Solution {
191
+ public int IntegerBreak (int n ) {
192
+ int [] f = new int [n + 1 ];
193
+ f [1 ] = 1 ;
194
+ for (int i = 2 ; i <= n ; ++ i ) {
195
+ for (int j = 1 ; j < i ; ++ j ) {
196
+ f [i ] = Math .Max (Math .Max (f [i ], f [i - j ] * j ), (i - j ) * j );
197
+ }
151
198
}
152
- let count = (n - 2 ) / 3 ;
153
- (3i32 ). pow (count as u32 ) * (n - count * 3 )
199
+ return f [n ];
154
200
}
155
201
}
156
202
```
157
203
158
204
#### C
159
205
160
206
``` c
207
+ #define max (a, b ) (((a) > (b)) ? (a) : (b))
208
+
161
209
int integerBreak (int n) {
162
- if (n < 4) {
163
- return n - 1;
210
+ int* f = (int* ) malloc((n + 1) * sizeof(int));
211
+ f[ 1] = 1;
212
+ for (int i = 2; i <= n; ++i) {
213
+ f[ i] = 0;
214
+ for (int j = 1; j < i; ++j) {
215
+ f[ i] = max(f[ i] , max(f[ i - j] * j, (i - j) * j));
216
+ }
164
217
}
165
- int count = (n - 2) / 3;
166
- return pow(3, count) * (n - count * 3);
218
+ return f[ n] ;
167
219
}
168
220
```
169
221
@@ -175,7 +227,7 @@ int integerBreak(int n) {
175
227
176
228
### 方法二:数学
177
229
178
- 当 $n \lt 4$ 时,$n$ 不能拆分成至少两个正整数的和 ,因此 $n - 1$ 是最大乘积。当 $n \ge 4$ 时,我们尽可能多地拆分 $3$,当剩下的最后一段为 $4$ 时,我们将其拆分为 $2 + 2$,这样乘积最大。
230
+ 当 $n \lt 4$ 时,由于题目要求至少拆分成两个整数 ,因此 $n - 1$ 是最大乘积。当 $n \ge 4$ 时,我们尽可能多地拆分 $3$,当剩下的最后一段为 $4$ 时,我们将其拆分为 $2 + 2$,这样乘积最大。
179
231
180
232
时间复杂度 $O(1)$,空间复杂度 $O(1)$。
181
233
@@ -269,6 +321,81 @@ function integerBreak(n: number): number {
269
321
}
270
322
```
271
323
324
+ #### Rust
325
+
326
+ ``` rust
327
+ impl Solution {
328
+ pub fn integer_break (n : i32 ) -> i32 {
329
+ if n < 4 {
330
+ return n - 1 ;
331
+ }
332
+ match n % 3 {
333
+ 0 => return (3 as i32 ). pow ((n / 3 ) as u32 ),
334
+ 1 => return (3 as i32 ). pow ((n / 3 - 1 ) as u32 ) * 4 ,
335
+ _ => return (3 as i32 ). pow ((n / 3 ) as u32 ) * 2 ,
336
+ }
337
+ }
338
+ }
339
+ ```
340
+
341
+ #### JavaScript
342
+
343
+ ``` js
344
+ /**
345
+ * @param {number} n
346
+ * @return {number}
347
+ */
348
+ var integerBreak = function (n ) {
349
+ if (n < 4 ) {
350
+ return n - 1 ;
351
+ }
352
+ const m = Math .floor (n / 3 );
353
+ if (n % 3 == 0 ) {
354
+ return 3 ** m;
355
+ }
356
+ if (n % 3 == 1 ) {
357
+ return 3 ** (m - 1 ) * 4 ;
358
+ }
359
+ return 3 ** m * 2 ;
360
+ };
361
+ ```
362
+
363
+ #### C#
364
+
365
+ ``` cs
366
+ public class Solution {
367
+ public int IntegerBreak (int n ) {
368
+ if (n < 4 ) {
369
+ return n - 1 ;
370
+ }
371
+ if (n % 3 == 0 ) {
372
+ return (int )Math .Pow (3 , n / 3 );
373
+ }
374
+ if (n % 3 == 1 ) {
375
+ return (int )Math .Pow (3 , n / 3 - 1 ) * 4 ;
376
+ }
377
+ return (int )Math .Pow (3 , n / 3 ) * 2 ;
378
+ }
379
+ }
380
+ ```
381
+
382
+ #### C
383
+
384
+ ``` c
385
+ int integerBreak (int n) {
386
+ if (n < 4) {
387
+ return n - 1;
388
+ }
389
+ if (n % 3 == 0) {
390
+ return (int) pow(3, n / 3);
391
+ }
392
+ if (n % 3 == 1) {
393
+ return (int) pow(3, n / 3 - 1) * 4;
394
+ }
395
+ return (int) pow(3, n / 3) * 2;
396
+ }
397
+ ```
398
+
272
399
<!-- tabs:end -->
273
400
274
401
<!-- solution:end -->
0 commit comments