从数学角度求解割绳子
#题目来源:https://leetcode.cn/problems/jian-sheng-zi-lcof/
题目不是很难,但是感觉是一个小小的数学问题,所以特意记录了下来。一般来说用数字分析的方法,贪心算法应该也都可以求解。
在数学上来考虑划分情况,借助于一个“经验”:和为4可以分为2x2,和为5可以分为2x3(而大于5本身),6可以分为3x3(大于2x2x2,更大于6本身)…
其实对于任意一个数字 n ≥ 3 n\geq3 n≥3都可以表示为 2 ∗ i + 3 ∗ j , 其中 i , j ≥ 0 2*i+3*j, 其中i,j\geq0 2∗i+3∗j,其中i,j≥0。而根据上面的规律只需说明: 2 i ∗ 3 j ≥ 2 ∗ i + 3 ∗ j ( 1 ) 2^i*3^j\geq 2*i+3*j (1) 2i∗3j≥2∗i+3∗j(1)因为只要这个式子满足,则对于一个更大的n’,总可以表示为 n + n+ n+某一个数字的划分,问题便又回到了之前的情况。
同时对(1)式两端取除以
2
i
∗
3
j
2^i*3^j
2i∗3j,只需比较
2
∗
i
2
i
∗
3
j
+
3
∗
j
2
i
∗
3
j
≤
1
\frac{2*i}{2^i*3^j} + \frac{3*j}{2^i*3^j}\leq1
2i∗3j2∗i+2i∗3j3∗j≤1
注意看
2
i
2^i
2i和
2
∗
i
2*i
2∗i,这是一个指数函数和一次函数(画图比较直观,实在不行就求导看一下),在i=1和i=2时相等,
i
>
2
i>2
i>2之后
2
i
>
2
∗
i
2^i>2*i
2i>2∗i,
3
j
3^j
3j同理。也就是说左端第一项
≤
1
3
j
\leq\frac{1}{3^j}
≤3j1,左端第二项
≤
1
2
i
\leq\frac{1}{2^i}
≤2i1,而当i或者j取0的时候,左端对应一项为0,所以左端最大为
1
2
+
1
3
=
5
6
<
1
\frac{1}{2}+\frac{1}{3}=\frac{5}{6}<1
21+31=65<1
上面说明了任意一个数字拆分成只含2和3的组合时能达到最大。下面说明具体拆分的时候的2和3的“分配问题”。
1、当 n = 3 ∗ k , k ≥ 1 n = 3*k, k\geq1 n=3∗k,k≥1,取全3最大:如果要添加2进去,先要去除部分3,只能添加的情况是:分段的长度是2和3的公倍数(如6=3+3或者2+2+2),意思是如果单独拿出一个3添加一个2,只后只能再加一个1,显然只会使得乘积变小。而显然在长度为2和3的公倍数情况下,按3划分要比按2划分好(2),所以还是取全3.
2、当 n = 3 ∗ k + 1 , k ≥ 1 n = 3*k+1,k\geq1 n=3∗k+1,k≥1,则假设有一部分是取的全三(这一部分如果有2又会出现第一种情况,所以不更改取法),则剩下一个1,而此时判断去掉一个3得到2x2结果好过1x3,所以拿掉一个3,加入两个2。
3、当 n = 3 ∗ k + 2 , k ≥ 1 n=3*k+2,k\geq1 n=3∗k+2,k≥1,同理假设前面的段取了全3,后面的只剩下一个2,之间乘上去就可以了。
补充说明:(2)式不是显然的,需要说明一下。
假设n可以同时整除2和3,则
n
=
2
∗
i
=
3
∗
j
,
其中
i
,
j
≥
1
n=2*i=3*j,其中i,j\geq1
n=2∗i=3∗j,其中i,j≥1
现在需要比较
2
i
与
3
j
2^i与3^j
2i与3j,只需要比较
2
n
2
与
3
n
3
2^\frac{n}{2}与3^\frac{n}{3}
22n与33n,只需要比较
2
1
2
与
3
1
3
2^\frac{1}{2}与3^\frac{1}{3}
221与331,而显然
8
=
(
2
1
2
)
6
<
(
3
1
3
)
6
=
9
8=(2^\frac{1}{2})^6<(3^\frac{1}{3})^6=9
8=(221)6<(331)6=9
class Solution:
def cuttingRope(self, n: int) -> int:
if n <= 3:
return n - 1
i = n // 3
j = n % 3
if j == 0:
return int(math.pow(3, i))
if j == 1:
return int(math.pow(3, i - 1) * 4)
if j == 2:
return int(math.pow(3, i) * 2)