剑指 Offer 14- I. 剪绳子

这道题乍一看感觉彷佛没思路,例如要切多少段绳子,每段绳子的长度是多少才能让绳子段数乘积最大,似乎组合性太多了,根本找不出来。但是可以换一个角度(动态规划),定义一个函数y=f(n),表示绳子长度为n时,满足题目要求的最大值。比如f(12),就表示绳子长度为12时,题目要求的最大值就是这个。

动态规划一般都会用到数组来记录每一个f(n)的值,并且计算过程是从下向上的,我们一般可以从题目或手动计算一些初始信息,比如f(0),f(1), f(2)等等,然后根据f(n)和f(n-1),f(n-2)来计算出f(n)的值。这里有点类似于斐波那契额书列和青蛙跳台阶那样的计算过程。重点是找到一种关系,f(n) 与f(n-1) 或者 f(n-2)等等的运算关系,即f(n) = F(f(n-1), f(n-2),...);

这道题,可以这样想,f(n) = f(n-i) * f(i),即将长度为n的绳子分成n-i和i的两段绳子长,但是我们不知道i为多少时可以取得最大值,所以需要来一次循环,让i=1一直到i=n/2,(可以到n,但是当i > n/2时就重复计算了,没必要),同时让一个辅助变量max去记录每一个这一轮循环中的最大值,最后把max赋值给f(n)。当然计算f(n)也需要一个循环。

还有一点特殊之处在于,如果当绳子的长度初始就是2, 3时,因为虽然此时他们本身的长度就是最大值,但是题目要求必须要切,所以此时,n = 2时max = 1, n = 3时max = 2。但是绳子被切分之后,剩下的绳子长度为2,3时,由于之前已经切过一次,所以此时可以不切,最大值就是2,3.因此我们在对初始值的处理中,n = 2, n = 3要进行特殊处理,返回特殊值。但是dp矩阵中,对应的n = 2,n = 3要选择最大值。

PS:当数据量很大,需要求模时,这种思路的代码我还没有搞出来。那种情况需要用到数学推导,面向答案编程。我在减绳子II中会写道。

代码如下:

class Solution {
    public int cuttingRope(int n) {
         if (n < 2) return -1;//必须要切,所以长度小于2的绳子不符合要求
        //当n小于等于3时,虽然本身就为最大值,但是题意必须切,所以单独处理
        if (n <= 3) return n - 1;
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
        int max = 0;
        //开始从下向上计算dp数组
        for (int i = 4; i <= n; i++) {
            for (int j = 1; j <= i / 2; j++) {
                max = Math.max(max, dp[i - j] * dp[j]);
            }
            dp[i] = max;
        }
        return dp[n];  
    }
}

路飞题解:https://leetcode-cn.com/problems/jian-sheng-zi-lcof/solution/mian-shi-ti-14-i-jian-sheng-zi-tan-xin-si-xiang-by/ 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值