• 剑指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]
    }
  • 相关阅读:
    linux开机启动服务的修改与查看
    我从百度来30万IP的经验
    JavaScript静态页面值传递之Cookie篇
    采用HttpModules来重写URLs(实践篇)
    JavaScript,5种调用函数的方法
    [JS]详尽解析window.event对象
    mysql锁定单个表的方法
    mysql常见错误提示及解决方法
    浏览器Chrome 3.0.195.21 Final
    svn windows和linux安装笔记
  • 原文地址:https://www.cnblogs.com/hzpeng/p/15112211.html
Copyright © 2020-2023  润新知