mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-10 04:06:51 +08:00
update 0343.整数拆分: 优化文本,优化代码风格
This commit is contained in:
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
dp[i]:分拆数字i,可以得到的最大乘积为dp[i]。
|
dp[i]:分拆数字i,可以得到的最大乘积为dp[i]。
|
||||||
|
|
||||||
dp[i]的定义讲贯彻整个解题过程,下面哪一步想不懂了,就想想dp[i]究竟表示的是啥!
|
dp[i]的定义将贯彻整个解题过程,下面哪一步想不懂了,就想想dp[i]究竟表示的是啥!
|
||||||
|
|
||||||
2. 确定递推公式
|
2. 确定递推公式
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ for (int i = 3; i <= n ; i++) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
注意 枚举j的时候,是从1开始的。从0开始的话,那么让拆分一个数拆个0的话,那么求最大乘积没有意义了。
|
注意 枚举j的时候,是从1开始的。从0开始的话,那么让拆分一个数拆个0,求最大乘积就没有意义了。
|
||||||
|
|
||||||
j的结束条件是 j < i - 1 ,其实 j < i 也是可以的,不过可以节省一步,例如让j = i - 1,的话,其实在 j = 1的时候,这一步就已经拆出来了,重复计算,所以 j < i - 1
|
j的结束条件是 j < i - 1 ,其实 j < i 也是可以的,不过可以节省一步,例如让j = i - 1,的话,其实在 j = 1的时候,这一步就已经拆出来了,重复计算,所以 j < i - 1
|
||||||
|
|
||||||
@ -109,15 +109,15 @@ for (int i = 3; i <= n ; i++) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
因为拆分一个数n 使之乘积最大,那么一定是拆分m个成近似相同的子数相乘才是最大的。
|
因为拆分一个数n 使之乘积最大,那么一定是拆分成m个近似相同的子数相乘才是最大的。
|
||||||
|
|
||||||
例如 6 拆成 3 * 3, 10 拆成 3 * 3 * 4。 100的话 也是拆成m个近似数组的子数 相乘才是最大的。
|
例如 6 拆成 3 * 3, 10 拆成 3 * 3 * 4。 100的话 也是拆成m个近似数组的子数 相乘才是最大的。
|
||||||
|
|
||||||
只不过我们不知道m究竟是多少而已,但可以明确的是m一定大于等于2,既然m大于等于,也就是 最差也应该是拆成两个相同的 可能是最大值。
|
只不过我们不知道m究竟是多少而已,但可以明确的是m一定大于等于2,既然m大于等于2,也就是 最差也应该是拆成两个相同的 可能是最大值。
|
||||||
|
|
||||||
那么 j 遍历,只需要遍历到 n/2 就可以,后面就没有必要遍历了,一定不是最大值。
|
那么 j 遍历,只需要遍历到 n/2 就可以,后面就没有必要遍历了,一定不是最大值。
|
||||||
|
|
||||||
至于 “拆分一个数n 使之乘积最大,那么一定是拆分m个成近似相同的子数相乘才是最大的” 这个我就不去做数学证明了,感兴趣的同学,可以自己证明。
|
至于 “拆分一个数n 使之乘积最大,那么一定是拆分成m个近似相同的子数相乘才是最大的” 这个我就不去做数学证明了,感兴趣的同学,可以自己证明。
|
||||||
|
|
||||||
5. 举例推导dp数组
|
5. 举例推导dp数组
|
||||||
|
|
||||||
@ -221,14 +221,14 @@ public:
|
|||||||
class Solution {
|
class Solution {
|
||||||
public int integerBreak(int n) {
|
public int integerBreak(int n) {
|
||||||
//dp[i] 为正整数 i 拆分后的结果的最大乘积
|
//dp[i] 为正整数 i 拆分后的结果的最大乘积
|
||||||
int[]dp=new int[n+1];
|
int[] dp = new int[n+1];
|
||||||
dp[2]=1;
|
dp[2] = 1;
|
||||||
for(int i=3;i<=n;i++){
|
for(int i = 3; i <= n; i++) {
|
||||||
for(int j=1;j<=i-j;j++){
|
for(int j = 1; j <= i-j; j++) {
|
||||||
// 这里的 j 其实最大值为 i-j,再大只不过是重复而已,
|
// 这里的 j 其实最大值为 i-j,再大只不过是重复而已,
|
||||||
//并且,在本题中,我们分析 dp[0], dp[1]都是无意义的,
|
//并且,在本题中,我们分析 dp[0], dp[1]都是无意义的,
|
||||||
//j 最大到 i-j,就不会用到 dp[0]与dp[1]
|
//j 最大到 i-j,就不会用到 dp[0]与dp[1]
|
||||||
dp[i]=Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j]));
|
dp[i] = Math.max(dp[i], Math.max(j*(i-j), j*dp[i-j]));
|
||||||
// j * (i - j) 是单纯的把整数 i 拆分为两个数 也就是 i,i-j ,再相乘
|
// j * (i - j) 是单纯的把整数 i 拆分为两个数 也就是 i,i-j ,再相乘
|
||||||
//而j * dp[i - j]是将 i 拆分成两个以及两个以上的个数,再相乘。
|
//而j * dp[i - j]是将 i 拆分成两个以及两个以上的个数,再相乘。
|
||||||
}
|
}
|
||||||
@ -254,7 +254,7 @@ class Solution:
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Go
|
### Go
|
||||||
```golang
|
```go
|
||||||
func integerBreak(n int) int {
|
func integerBreak(n int) int {
|
||||||
/**
|
/**
|
||||||
动态五部曲
|
动态五部曲
|
||||||
@ -264,40 +264,25 @@ func integerBreak(n int) int {
|
|||||||
4.确定遍历顺序
|
4.确定遍历顺序
|
||||||
5.打印dp
|
5.打印dp
|
||||||
**/
|
**/
|
||||||
dp:=make([]int,n+1)
|
dp := make([]int, n+1)
|
||||||
dp[1]=1
|
dp[1] = 1
|
||||||
dp[2]=1
|
dp[2] = 1
|
||||||
for i:=3;i<n+1;i++{
|
for i := 3; i < n+1; i++ {
|
||||||
for j:=1;j<i-1;j++{
|
for j := 1; j < i-1; j++ {
|
||||||
// i可以差分为i-j和j。由于需要最大值,故需要通过j遍历所有存在的值,取其中最大的值作为当前i的最大值,在求最大值的时候,一个是j与i-j相乘,一个是j与dp[i-j].
|
// i可以差分为i-j和j。由于需要最大值,故需要通过j遍历所有存在的值,取其中最大的值作为当前i的最大值,在求最大值的时候,一个是j与i-j相乘,一个是j与dp[i-j].
|
||||||
dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]))
|
dp[i] = max(dp[i], max(j*(i-j), j*dp[i-j]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dp[n]
|
return dp[n]
|
||||||
}
|
}
|
||||||
func max(a,b int) int{
|
func max(a, b int) int{
|
||||||
if a>b{
|
if a > b {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Rust
|
|
||||||
```rust
|
|
||||||
pub fn integer_break(n: i32) -> i32 {
|
|
||||||
let n = n as usize;
|
|
||||||
let mut dp = vec![0; n + 1];
|
|
||||||
dp[2] = 1;
|
|
||||||
for i in 3..=n {
|
|
||||||
for j in 1..i-1 {
|
|
||||||
dp[i] = dp[i].max((i - j) * j).max(dp[i - j] * j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dp[n] as i32
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Javascript
|
### Javascript
|
||||||
```Javascript
|
```Javascript
|
||||||
var integerBreak = function(n) {
|
var integerBreak = function(n) {
|
||||||
@ -313,6 +298,21 @@ var integerBreak = function(n) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
```rust
|
||||||
|
pub fn integer_break(n: i32) -> i32 {
|
||||||
|
let n = n as usize;
|
||||||
|
let mut dp = vec![0; n + 1];
|
||||||
|
dp[2] = 1;
|
||||||
|
for i in 3..=n {
|
||||||
|
for j in 1..i-1 {
|
||||||
|
dp[i] = dp[i].max((i - j) * j).max(dp[i - j] * j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dp[n] as i32
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### TypeScript
|
### TypeScript
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
Reference in New Issue
Block a user