Loading

剑指Offer14-I|LeetCode343.剪绳子|整数拆分

题目

给你一根长度为 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。

示例 1:

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

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

2 <= n <= 58

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题方法

推荐视频:https://www.bilibili.com/video/BV1Nt4y1D7gh?from=search&seid=9284550418823896015

这道题跟数学有关:
当绳子长度为2的时候拆分成两个长度为1的绳子 它们的乘积为1
当绳子长度为3的时候可以拆分[1,1,1][1,2] 最大乘积为2
当绳子长度为4的时候可以拆分[1,1,1,1][1,3][1,2,1] 最大乘积为3
当绳子长度为5的时候可以拆分[1,1,1,1,1][1,2,2],[1,2,1,1],[2,3] 最大乘积为6
当绳子长度为6的时候可以拆分[3,3][3,2,1][2,4][1,1,4] 最大乘积为9
当绳子长度为7的时候可以拆分[1,6][3,3,1][3,4][2,5] 最大乘积为12
...
从上面的举例可以发现,想要乘积最大,需要尽量将绳子划分为长度3。
如果绳子长度 n % 3 = 0,也就是说绳子总长度刚好划分为每段长度为3的小绳子,那么最大的乘积就是 3^(n/3)
如果绳子长度 n % 3 = 1,也就是说绳子总长度划分为长度3的绳子后还剩1,
从上面举例绳子长度7可以发现,7划分为[3,3,1]显然没有[3,4]乘积大,
同理,我们就要把剩余的1和最后一段3的绳子合并,那么最大的乘积为 3^(n/3-1)*4
如果绳子长度 n % 3 = 2,也就是绳子总长度划分长度3后还剩2,
我们可以想:假设划分为[3,3,2][3,5][3,3,1,1]
我们可以看出[3,3,2]的乘积就是最大的了,如果和最后一段拼接为[3,5],乘积反而更小
所以如果绳子长度 n % 3 = 2,绳子的最大乘积就是 3^(n/3)*2

动态规划

贪心算法

数学

代码

// 数学
func cuttingRope(n int) int {
	if n <= 3 {
		return n-1
	}
	quotient := n/3
	remainder := n%3
	if remainder == 0{
		return int(math.Pow(3,float64(quotient)))
	}else if remainder == 1 {
		return int(math.Pow(3,float64(quotient-1))) * 4
	}
	return  int(math.Pow(3,float64(quotient))) * 2
}

// 贪心 时间复杂度O(n) 空间复杂度O(1)
func cuttingRope2(n int) int {
	if n == 2{
		return 1
	}
	if n == 3{
		return 2
	}
	if n == 4{
		return 4
	}
	result := 1
	for n > 4{
		result *= 3
		n -= 3
	}
	result *= n
	return result
}

// 动态规划 时间复杂度:O(n^2) 空间复杂度:O(n)
func cuttingRope3(n int) int {
	dp := make([]int,n+1)
	dp[2] = 1
	max := func(a,b int) int {
		if a > b{
			return a
		}
		return b
	}
	// 外层循环为绳子长度,内层循环获取比较最大乘积
	// 假如现在为长度10的绳子
	// 指剪一刀划分为两根绳子:(i-j)*j: 9*1,8*2,7*3,6*4...
	// 也可以根据前面绳子已经得到的最大乘积dp[i-j]*j: dp[9]*1,dp[8]*2,dp[7]*3...
	// 然后比较这两者,获取最大乘积方案
	for i := 3;i <= n;i++{
		for j := 1;j < i;j++{
			dp[i] = max(dp[i],max(j*(i-j),dp[i-j]*j))
		}
	}
	return dp[n]
}
posted @ 2021-08-07 16:08  励码万言  阅读(30)  评论(0编辑  收藏  举报