Leetcode-每日一题【剑指 Offer 14- II. 剪绳子 II】

题目

2、3、3的三段,此时得到的最大乘积是18。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1

示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

提示:

  • 2 <= n <= 1000

解题思路

1.题目要求我们将绳子剪切为乘积最大的 m 段,这个题的解题思路与剑指 Offer 14- I. 剪绳子基本相同,大家可以先去学习一下。唯一有一点不同的是,这道题需要我们取模。

2.那在这里我们只讲解一下大数取余的方法,

余数定理(推导过程略):

(ab)%p =((a%p)(b%p))%p

在每次乘法运算后都加上求余操作,则最终的结果就是想要求得的余数(在代码中体现在 pow 函数的for()循环中 res = (res * a) % p;就是在每次乘法运算后都加上求余操作)

因此: 循环求余法 = 循环求幂次+每次乘法运算后求余数 。所以,大数求余的本质实际就是通过“求幂次的方法+余数定理”,将原本要一次完成的操作,分解到了求幂次过程的每一次循环中,每次乘法操作都求一次余数。

3.因为在计算过程中res有可能超出类型,所以我们将res设置为 long 类型。那在cuttingRope() 函数的返回值中,我们就要将pow返回的 long 类型强转为 int 类型,但是在 mod ==1 和 mod == 2 时,有可能 pow 的返回值乘以 4 或者乘以 2 后依旧为 long 类型,所以我们要将相乘后的值再次取余后再进行强转。

代码实现

class Solution {
    public int cuttingRope(int n) {
         if(n <= 2){
            return 1;
        }
        if(n == 3){
            return 2;
        }
        int res = n / 3;
        int mod = n % 3;
        int p = 1000000007;
        if(mod == 0){
            return (int)pow(3,res);
        }else if(mod == 1){
            return (int)(pow(3,res - 1) * 4 % p);
        }else {
            return (int)(pow(3,res) * 2 % 1000000007);
        }

    }
    long pow(int a, int k){
        long res = 1;
        int p = 1000000007;
        for(int i = 1; i <= k; i++){
            res = (res * a) % p;
        }
        return res;
    }
}

测试结果

Leetcode-每日一题【剑指 Offer 14- II. 剪绳子 II】_第1张图片

 

你可能感兴趣的:(算法每日一题,leetcode,算法,职场和发展,java)