题目

image.png

思路

  • 思路一:暴力递归,对于每个大于1的数字来说,它都可以有若干个2或3组成,并且拆成2或3的积最大,因此,递归的时候我们可以将数拆分为n-2或n-3,取它们的最大值
  • 思路二:备忘录
  • 思路三:动态规划,定义dp[i]表示切分后最大能表示的数,dp[i] = Math.max(dp[i-2]2,dp[i-3]3)
  • 思路四:优化dp数组的动态规划,通过观察dp数组即可

    代码

    1. //1.暴力递归
    2. public int cuttingRope(int n) {
    3. if (n == 2 || n == 1) return 1;
    4. if (n == 3) return 2;
    5. return recur(n);
    6. }
    7. //当n > 1时,由于每个数由若干个2、3组成,所以每次每个数可以分割为2或3,并且拆成2或3的积最大
    8. public int recur(int n) {
    9. if (n <= 3) return n;
    10. return Math.max(recur(n - 2) * 2, recur(n - 3) * 3);
    11. }
    12. //2.备忘录
    13. int[] dp;
    14. public int cuttingRope(int n) {
    15. if (n == 2 || n == 1) return 1;
    16. if (n == 3) return 2;
    17. dp = new int[n + 1];
    18. return recur(n);
    19. }
    20. public int recur(int n) {
    21. if (n <= 3) return n;
    22. if (dp[n] != 0) return dp[n];
    23. dp[n] = Math.max(recur(n - 2) * 2, recur(n - 3) * 3);
    24. return dp[n];
    25. }
    26. //3.动态规划
    27. public int cuttingRope(int n) {
    28. if (n == 2 || n == 1) return 1;
    29. if (n == 3) return 2;
    30. //dp[i]表示当前i可分割后最大值
    31. int[] dp = new int[n + 1];
    32. dp[1] = 1; dp[2] = 2; dp[3] = 3;
    33. for(int i = 4; i <= n; i++) {
    34. dp[i] = Math.max(dp[i - 2] * 2, dp[i - 3] * 3);
    35. }
    36. return dp[n];
    37. }
    38. //4.由于每次只用到了前2个变量,所以可以优化dp数组
    39. public int cuttingRope(int n) {
    40. if (n == 2 || n == 1) return 1;
    41. if (n == 3) return 2;
    42. int p1 = 1, p2 = 2, p3 = 3;
    43. for(int i = 4; i <= n; i++) {
    44. int t = p3;
    45. p3 = Math.max(p2 * 2, p1 * 3);
    46. p1 = p2;
    47. p2 = t;
    48. }
    49. return p3;
    50. }

    剪绳子