题目来自LeetCode,链接:面试题14- II. 剪绳子 II。题目其实跟前一道题一样,只不过是数的范围更大了,所以有越界的危险。
照搬上一道题的方法,只是这里不能再直接调用pow()
计算了,需要手动计算防止越界。假设我们要计算两个数a、b
的乘积相对于m
的模,可以先改写如下:a=k1*m+c1
、b=k2*m+c2
,则有a*b=k1*k2*m*m+k1*c2*m+k2*c1*m+c1*c2
,也就是(a*b)%m=(c1*c2)%m=((a%m)*(b%m))%m
,这就是之后防止越界用到的公式了。时间复杂度为
O
(
n
)
O(n)
O(n),空间复杂度为
O
(
1
)
O(1)
O(1)。
JAVA版代码如下:
class Solution {
private int remainder(int num, int pow, int mod) {
int result = 1;
for (int i = 0; i < pow; ++i) {
result = (int)(((long)(result % mod) * (long)(num % mod)) % mod);
}
return result;
}
public int cuttingRope(int n) {
int mod = 1000_000_007;
if (n <= 3) {
return n - 1;
}
int p = n / 3;
int q = n % 3;
if (q == 2) {
return (int)((remainder(3, p, mod) * 2L) % mod);
}
if (q == 1) {
return (int)((remainder(3, p - 1, mod) * 4L) % mod);
}
return remainder(3, p, mod);
}
}
提交结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/d174880fd423ecbdc9bbb6268d2d40dd.png)
上面的方法也可以改写成贪心算法如下:
JAVA版代码如下:
class Solution {
public int cuttingRope(int n) {
if (n <= 3) {
return n - 1;
}
int mod = 1000_000_007;
int result = 1;
while (n > 4) {
result = (int)((result * 3L) % mod);
n -= 3;
}
result = (int)((result * 1L * n) % mod);
return result;
}
}
提交结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/3c69db91f05d10a00f9cf70e05b77ccc.png)
Python版代码如下:
class Solution:
def cuttingRope(self, n: int) -> int:
if n <= 3:
return n - 1
result = 1
mod = 1000000007
while n > 4:
result = (result * 3) % mod
n -= 3
result = (result * n) % mod
return result
提交结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/a77b3f00bc14a40e948ad5b4f7c64c17.png)