题目描述
给你一根长度为 n n n 的绳子,请把绳子剪成 m m m 段 ( m , n 都 是 整 数 , 2 ≤ n ≤ 58 并 且 m ≥ 2 ) (m,n都是整数,2 \leq n \leq 58 并且 m \geq 2) (m,n都是整数,2≤n≤58并且m≥2) 。每段的绳子的长度记为k[0]、k[1]、k[2]、……、k[m-1]。k[0]k[1]k[2]……k[m-1]可能的最大乘积是多少?
样例
Input: 8
Output: 18
// 当绳子长度为8时,将其剪成长度分别为2,3,3的三段,此时得到最大乘积18。
解题思路
-
描述
这里有一个推导——为满足最大乘积尽可能的大,需将n尽可能分成多的3,同时如果n%3 == 1则分为两个2。
证明如下:(假定 n > 0 ,n = n1 + n2 + …… + nk)
- 假定存在 n i ≥ 5 ni \geq 5 ni≥5,则有 3 × ( n i − 3 ) ≥ n i 3 \times (ni - 3) \geq ni 3×(ni−3)≥ni。那么最大乘积要尽可能大,ni一定小于5。
- 对于 n i = 4 ni = 4 ni=4 , 4 = 2 × 2 4 = 2 \times 2 4=2×2。那么对于4等价于两个2相乘。
- 不可能存在ni = 1的情况,因为ni对乘积毫无影响。
- 假设存在3个及其以上的2,由于 2 × 2 × 2 < 3 × 3 2 \times 2 \times 2 < 3 \times 3 2×2×2<3×3,那么2的数量只可能最多是两个。
-
实现代码:
int maxProductAfterCutting(int length) { if (length <= 3) { return 1 * (length - 1); } int result = 1; if (length % 3 == 1) { result *= (2 * 2); length -= 4; } else if(length % 3 == 2) { result *= 2; length -= 2; } while (length) { result *= 3; length = length - 3; } return result; }
-
复杂度分析
时间复杂度: ≈ O ( n ) \approx O(n) ≈O(n)
空间复杂度: O ( 1 ) O(1) O(1)
使用辅助变量result