题目链接:剪绳子
思路:
-
暴力(会超时)。假设输入为n,那么当某个位置的左边长度为
i
,右边长度为n-i
时,可以枚举出四种情况:- 左边进行分段,右边进行分段。那么变成递归的行为,对左右段递归调用本方法。
- 左边不进行分段,右边进行分段。同理,对右边递归调用。左边长度为本身。
- 左边进行分段,右边不进行分段。同理,对左边递归调用。右边长度为本身。
- 左边不进行分段,右边不进行分段。那么,左右长度都为本身,此时,该绳子只分了2段。
-
动态规划。设置一个数组dp[n],dp[i]表示以长度为i的最大分段乘积。状态转移方程为(dp[n] = max_{i=1,2,...,n-1}{dp[n-i]*i, (n-i)*i})。当长度为n-1时,知道dp[n-1],此时再增加1个长度,总长度变为n,那么进行分段时,右边长度为i,左边最大分段长度为dp[n-i],但左边不存在不分段的情况,因此要考虑(dp[n-i]*i)是否大于((n-i)*i)的情况。
代码:
//动态规划
class Solution {
public int cuttingRope(int n) {
int[] dp = new int[n+1];
dp[0] = dp[1] = dp[2] = 1;
for(int i=2; i<=n; i++){
for(int j=1; j<=(i>>1); j++){
int t = Math.max(j * (i - j), dp[i - j] * j);
dp[i] = Math.max(dp[i], t);
}
}
return dp[n];
}
}
//暴力,n大于30时会超时
class Solution {
public int cuttingRope(int n) {
if(n == 1 || n == 2) return 1;
if(n == 3) return 2;
if(n == 4) return 2;
int max = 0;
for(int i=1; i<=(n>>1); i++){
int left = cuttingRope(i);
int right = cuttingRope(n-i);
int t = Math.max(i * (n - i), left * right);
t = Math.max(t, i * right);
t = Math.max(t, left * (n - i));
max = Math.max(max, t);
}
return max;
}
}
执行用时:1 ms, 在所有 Java 提交中击败了43.38%的用户
内存消耗:35.4 MB, 在所有 Java 提交中击败了36.17%的用户