Go&Java算法之剪绳子

172 阅读2分钟

这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战

剪绳子

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m - 1] 。请问 k[0]k[1]...*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为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

题解

算法一:快速幂算法(Java)

当 n≤3 时,按照规则应不切分,但由于题目要求必须剪成 m>1 段,因此必须剪出一段长度为 1 的绳子,即返回 n - 1 。

当 n>3 时,求 n 除以 3 的 整数部分 a 和 余数部分 b (即 n = 3a + b ),并分为以下三种情况(设求余操作符号为 "⊙" ):

当 b = 0 时,直接返回 3^a⊙1000000007;

当 b = 1 时,要将一个 1 + 3 转换为 2+2,因此返回 3^a−1×4)⊙1000000007;

当 b = 2 时,返回 3^a×2)⊙1000000007。

class Solution {
    
    public int cuttingRope(int n) {
        if(n < 4) {
            return n - 1;
        }
        int a = n / 3;
        int b = n % 3;
        if(b == 0) {
            return (int) (myPow(3,a) % 1000000007);
        }else if(b == 1) {
            return (int) ((myPow(3,a - 1) * 4) % 1000000007);
        }else {
            return (int) ((myPow(3,a) * 2) % 1000000007);
        }
    }

    public long myPow(long  base, int num) {
        long res = 1;
        while(num > 0) {
            if((num & 1) == 1) {
                res *= base;
                res %= 1000000007;
            }
            base *= base;
            base %= 1000000007;
            num >>= 1;
        }
        return res;
    }
}

时间复杂度:O(log2N)

空间复杂度:O(1)

算法一:快速幂算法(Go)

思路同上

const modNum=1000000007
func cuttingRope(n int) int {
   if n<=3{
       return n-1
   }
   k,v:=n/3,n%3
   if v==0{
       return Pow(3,k) 
   }else if v==1{
       return Pow(3,k-1)*4%modNum
   }
    return Pow(3,k)*2%modNum
}
func Pow(x int,y int)int{
	var result=1
	for y>0{
		if y%2==1{
			result=result*x%modNum
		}
		y=y/2
		x=x*x%modNum
	}
	return result
}

时间复杂度:O(log2N)

空间复杂度:O(1)