343. 整数拆分
题目描述
给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。
示例1:
输入:n=2n=2n=2
输出:111
示例2:
输入:n=10n=10n=10
输出:363636
思路
本题只看题目的话真的不是那种第一眼就会想到动态规划的题。但是题目中的乘积最大化在一定程度上也是一种提示。这里首先规定一个动态规划数组dp[i],其表示拆分数字i所得到的最大乘积。
得到数组后,可以进行初始化。这里出现了第一个难点,初始化从几开始。正常思路肯定是从0啊,但是根据dp的定义,0和1又实在没什么意义。看了答案,直接从2开始,是的,答案直接说出了我的所有想法,“要不就规定为0或者1?”我就是这么想的。
初始化之后需要写出递推。这里比较好想了就,第j个的最大化,就是前一个的最大化×j。
解法
class Solution {
public int integerBreak(int n) {
int[] dp = new int[n+1];
dp[2] = 1;
for(int i = 3;i<=n;i++){
for(int j = 1;j<=i-j;j++){
dp[i] = Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j]));
}
}
return dp[n];
}
}
总结
动态规划的代码看着简单,但里面的思考量真是一点都不少啊。
96. 不同的二叉搜索树
题目描述
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例1:
输入:n=3n=3n=3
输出:555
示例2:
输入:n=1n=1n=1
输出:111
思路
如果说,上一题是不太好想到动态规划但有些提示。那么这题,如果不是放在了动态规划类里面,这辈子我都不可能想到用动态规划的,二叉搜索树,真的很难想到动态规划。
直接上答案思路:
首先,规定一个dp[i],那么它表示的是元素为1,2,3为头节点搜索树的数量之和。
而元素1为头节点搜索树的数量=右子树有2个元素的搜索树左子树有0个元素的搜索树
元素2为头节点搜索树的数量=右子树有1个元素的搜索树数量左子树有1个元素的搜索树数量
元素3为头节点搜索树的数量 = 右子树有0个元素的搜索树数量*左子树有2个元素的搜索树数量
有2个元素的搜索树数量就是dp[2]
有1个元素的搜索树数量就是dp[1]
有0个元素的搜索树数量就是dp[0]
所以dp[3] = dp[2]*dp[0]+dp[1]*dp[1]+dp[0]*dp[2]
答案看到这,人都有点麻了,这不是个中等题吗?怎么做出了一种困难的感觉。
解法
class Solution {
public int numTrees(int n) {
int[] dp = new int[n+1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2;i<=n;i++){
for(int j = 1;j<=i;j++){
dp[i] += dp[j-1]*dp[i-j];
}
}
return dp[n];
}
}
总结
如果不是亲手写上去的,我真的很难相信这个简单的代码对应的是一道如此难想的题。不过这也从另一个角度说明了动态规划实在是一种很好的方式,可以使复杂的题目简单化。
文章介绍了两道使用动态规划解决的算法问题,一个是求解正整数拆分以获得最大乘积,另一个是计算不同节点数的二叉搜索树的种类。动态规划在这两个问题中起到了简化复杂性的作用,通过定义状态转移方程,分别得出了解决方案。
1101

被折叠的 条评论
为什么被折叠?



