【题目】
给你一根长度为 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/problems/jian-sheng-zi-lcof
【思路1】动态规划
dp[i]表示当前i长度的绳子可以得到的最大乘积
每次对i长度的绳子剪2~i-1长度
判断dp[i],i*(i-j),i*dp[i-j]的大小,保留最大的
【代码1】
class Solution { public int cuttingRope(int n) { int[] dp = new int[n+1]; dp[2] = 1; // dp[i]表示i长度的绳子的最大乘积,从2开始 for(int i=3;i<n+1;i++){ //j 表示本次切割的长度 for(int j=2;j<i;j++){ //dp[i] 保存上次分割方式的最大值 //j*(i-j) 如果i-j部分不在切割的情况 //j*dp[i-j] 如果i-j部分继续切割的情况 dp[i] = Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j])); } } return dp[n]; } }
【思路2】贪心
切分规则:
最优: 3 。把绳子尽可能切为多个长度为 3 的片段,留下的最后一段绳子的长度可能为 0,1,2 三种情况。
次优: 2 。若最后一段绳子长度为 2 ;则保留,不再拆为 1+1。
最差: 1 。若最后一段绳子长度为 1 ;则应把一份 3+1 替换为 2+2,因为 2×2>3×1。
当 n≤3时,按照规则应不切分,但由于题目要求必须剪成 m>1 段,因此必须剪出一段长度为 1 的绳子,即返回 n−1 。
当 n>3 时,求 nn 除以 3 的 整数部分 a 和 余数部分 b (即 n=3a+b ),并分为以下三种情况:
当 b=0 时,直接返回 3a;
当 b=1 时,要将一个 1+3 转换为 2+2,因此返回 3a−1×4;
当 b=2时,返回 3a×2。
【代码】
class Solution { public int cuttingRope(int n) { if(n<=3){ return n-1; } int a = n/3; int b = n%3; if(b==0){ return (int)Math.pow(3,a); }else if(b==1){ return (int)Math.pow(3,a-1)*4; }else{ return (int)Math.pow(3,a)*2; } } }
标签:14,Offer,int,绳子,长度,3a,dp,乘积 From: https://www.cnblogs.com/End1ess/p/17320567.html