标签:定义 假设 返回 tco 情况 组元 n+1 etc 具体流程
题目:给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例:
输入: 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明: 你可以假设 n 不小于 2 且不大于 58。
分析:
1.定义一个状态转移数组dp,dp[i]表示数字i拆分为至少两项之和后,拆分后的数字之间的最大乘积。
2.寻找关系式,那么如何确定dp[i]的最大值呢?首先我们要确定它有哪些取值的可能,对于拆分之和的数字的乘积,这个乘积可能是两个数字的乘积,也可能是多个数字之间的乘积,那么如何表示这两种乘积呢?
1)对于两个数的乘积,就是一个小于i的数j,和i-j之间的乘积,即 (i - j)* j;
2)对于多个数之间的乘积,就是相当于一个小于i的数j,和dp[i-j]的乘积,即 j * dp[i-j] ;
3.初始条件,根据题目,n从2开始,多以dp[2] = 1;
4.需要借助于双层循环,外层循环从3开始,到n结束,因此状态转移数组的空间大小是n+1,内层循环是为了寻找当前i的最大拆分数字之积
首先的代码如下:
public int integerBreak(int n) { if (n==2) return 1; int[] dp = new int[n+1]; dp[2] = 1; for (int i = 3; i <= n ; i++) { for (int j = 1; j < i; j++) { dp[i] = Math.max(Math.max(dp[i],j*(i-j)),j*dp[i-j]); } } return dp[n]; }
题目:给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例:
输入: n = 12 输出: 3 解释: 12 = 4 + 4 + 4.
分析:这个题的解决思路和上面那个题的解决思路相似,具体流程如下:
1.定义一个状态转移数组dp,dp[i]表示数字i由完全平方数组成的最少个数;
2.寻找关系式,如果i本身就是一个完全平方数,那么这就是最理想的情况了,dp[i]的值直接为1;如果不是,那么就需要从小于1~i-1的数字中去寻找了,那么此时dp[i] = dp[j] + dp[i-j],即i拆分为j和i-j,二者的最少个数,就是i的最少个数。
3.初始值,外层循环是从1开始遍历,到n结束,因此dp[1] = 1,内层循环用于寻找当前遍历的数字i的拥有完全平方数的最少个数,如果i不是完全平方数字,那么在i自己寻找之前,dp[i]设置为一个最大值。
实现代码:
public int numSquares(int n) { if ((int) Math.sqrt(n) - Math.sqrt(n) == 0){ return 1; } int[] dp = new int[n+1]; dp[1] = 1; for (int i = 2; i <= n; i++) { if ((int) Math.sqrt(i) - Math.sqrt(i) == 0){ dp[i] = 1; }else { dp[i] = Integer.MAX_VALUE; for (int j = 1; j < i; j++) { dp[i] = Math.min(dp[i],dp[j] + dp[i-j]); } } } return dp[n]; }
题目:一条包含字母 A-Z
的消息通过以下方式进行了编码:
‘A‘ -> 1
‘B‘ -> 2
...
‘Z‘ -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
示例:
输入: "12" 输出: 2 解释: 它可以解码为 "AB"(1 2)或者 "L"(12)
分析:对于给定的一串数字,能够正确的解码的前提条件是,这个数字或者它和它前面的一个数字组成的两位数字位于1~26之间,否则都是不能被正确解码的,具体的过程如下:
1.定义一个数组dp,dp[i]表示前i个字符构成的子串所拥有的解码方法的总数;
2.寻找关系式:对于能够解码的情况有两种:
一种是,对于当前遍历的这个字符,被用于单独解码,它只要大于‘0‘,那么就能够被解码,在它被用来单独解码的时候,它的前i-1个字符构成的子串的解码方法总数是不变的,也就是相当于在前i-1个字符构成的子串末尾增加一个单独编码的字符,并不会影响整体编码,它们的解码方法总数一致;
另一种是,对于当前遍历的这个字符,不是被用于单独编码的,它被用来和它的前一个字符组成一个二位数,如果这个二位数在10~26之间,对于这种的组合编码的情况下,前i个字符构成的子串含有的解码方法总数是和它的前i-2个字符构成的子串的解码方法总数是一致的,即在前i-2个字符构成的子串的末尾加上一个组合编码数,并不会影响前i-2字符的解码情况。
这两个情况需要逐一判断,才不会漏掉所有的解码方法
3.初始值,dp[0] = 1,dp[1] = 1,这里d[1]代表字符串的第一个字符,dp[0]没有实际的含义,只是充当一个数字1存在,此处设置dp[0]为1,纯粹是为了i=1时:
第i个字符和第i-1个字符能够构成合法解码数字的时候,使解码方法总数加1。因为此时子串的总个数是2,比如226,子串22解码个数包括2、2和22。为22的时候,相对于dp[2]的值,应该是dp[1]的值再加上1,因为22也构成了一个解码方法,而dp[0]并没有对应的子字符串,所以用来当做一个1。
实现代码:
public int numDecodings(String s) { if (s.charAt(0)==‘0‘) return 0; if (s.length()==1&&s.charAt(0) > ‘0‘) return 1; int n = s.length(); int[] dp = new int[s.length()+1]; dp[0] = 1; dp[1] = 1; for (int i = 1; i < n; i++) { int two_nums = s.charAt(i) - ‘0‘ + (s.charAt(i-1) -‘0‘)*10; if (s.charAt(i) > ‘0‘) dp[i+1] = dp[i]; if (two_nums > 9 && two_nums <=26) dp[i+1] += dp[i-1]; if (dp[i+1]==0) return 0; } return dp[n]; }
一定要根据题目的要求找清楚数组元素之间的推导关系!!!
动态规划学习之LeetCode分割整数相关题目(第343、279、91题)
标签:定义 假设 返回 tco 情况 组元 n+1 etc 具体流程
原文地址:https://www.cnblogs.com/yxym2016/p/12641507.html