Leetcode——剪绳子

Posted Yawn,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——剪绳子相关的知识,希望对你有一定的参考价值。

1. 题目

2. 题解

(1)动态规划

  • 我们想要求长度为n的绳子剪掉后的最大乘积,可以从前面比n小的绳子转移而来
  • 用一个dp数组记录从0到n长度的绳子剪掉后的最大乘积,也就是dp[i]表示长度为i的绳子剪成m段后的最大乘积,初始化dp[2] = 1
  • 我们先把绳子剪掉第一段(长度为j),如果只剪掉长度为1,对最后的乘积无任何增益,所以从长度为2开始剪
  • 当 i≥2 时,假设对正整数 i 拆分出的第一个正整数是 j(1≤j<i),则有以下两种方案:
    将 i 拆分成 j 和 i−j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j×(i−j);
    将 i 拆分成 j 和 i−j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j×dp[i−j]。
  • 第一段长度j可以取的区间为[2,i),对所有j不同的情况取最大值,因此最终dp[i]的转移方程为
    dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))
  • 最后返回dp[n]即可
class Solution {
    public int cuttingRope(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for(int i = 3; i < n + 1; i++){
            for(int j = 2; j < i; j++){
               //为什么可以固定一个j呢,因为j在遍历中都能被取到
                dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
            }
        }
        return dp[n];
    }
}

如果看不懂的话,来个最容易懂的:

  • 固定划分点,继续看子划分区间能不能继续划分
class Solution {
    public int cuttingRope(int n) {
        int[] dp = new int[n + 1];
        //i表示绳子长度
        for(int i = 2;i <= n;i++){
            //j表示分的段的长度,小于i
            for(int j = 1;j < i;j++){
                //都不能分了
                int a = j * (i - j);
                //j不能分,i - j能分
                int b = j * dp[i - j];
                //以此类推
                int c = dp[j] * (i - j);
                int d = dp[j] * dp[i - j];
                int e = dp[i];
                dp[i] = Math.max(Math.max(Math.max(a,b),Math.max(c,d)),e);
            }
        }
        return dp[n];
    }
}

(2)贪心

核心思路是:尽可能把绳子分成长度为3的小段,这样乘积最大
步骤如下:

  • 如果 n == 2,返回1
  • 如果 n == 3,返回2,两个可以合并成n小于4的时候返回n - 1
  • 如果 n == 4,返回4
  • 如果 n > 4,分成尽可能多的长度为3的小段,每次循环长度n减去3,乘积res乘以3;最后返回时乘以小于等于4的最后一小段
class Solution {
    public int cuttingRope(int n) {
        if(n == 2)  
        	return 1;
        if(n == 3)  
        	return 2;
        int res = 1;
        while(n > 4){
            res *= 3;
            n -= 3;
        }
        return res * n;
    }
}

当 n 很大时:

class Solution {
    public int cuttingRope(int n) {
        if(n == 2)  
        	return 1;
        if(n == 3)  
        	return 2;
        long a = 1;
        long mod = 1000000007;
        while(n > 4){
            n = n - 3;
            a = (a * 3) % mod;
        }
        long ans = a * n % mod;
        return (int)ans;
    }
}

以上是关于Leetcode——剪绳子的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode---剑指Offer题14---剪绳子

Leetcode---剑指Offer题14---剪绳子

LeetCode面试题14-2. 剪绳子II

LeetCode面试题14-2. 剪绳子II

Leetcode——剪绳子

LeetCode(剑指 Offer)- II. 剪绳子 II