给定一个正整数 n
,将其拆分为 k
个 正整数 的和( k >= 2
),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。
解题思路:动态规划,就是不断尝试,例如我们已经知道1拆分后的乘积最大值是1
,2是2,相当于1*2的最大值
如果是3相当于 1*2的最大值,2*1的最大值,或者是1*2;
以此类推本次的乘积最大值都可以由上一次的状态进行推导.
开始动态规划:
1,dp数组含义dp[i]代表数字 i 拆分之后的最大乘积为 dp[i]
2,确定递推公式, dp[i] 可以从 1 到 j 进行遍历遍历过程中 dp[i] 的最大值就可以是
j*(i-j) 可以理解为拆分为两个数字想乘
亦或是 j*dp[i-j] 可以理解为拆分成两个以上数字相乘
由此得出递推公式dp[i]=max(j*(i-j),j*dp[i-j],dp[i])
3,dp初始化
dp[2]=1即可,dp[0]和dp[1]做拆分没有意义,我们的循环直接从3开始
4,循环遍历
采用两层for循环,一层控制数字i~n另一层循环求出 dp[i]
完整代码:
class Solution {
public int integerBreak(int n) {
//动态规划
//dp数组的含义:dp[i]代表第i个整数可拆分的整数的最大乘积
int[] dp=new int[n+1];
//初始化
dp[2]=1;
//递推公式
// dp[i]=Math.max(Math.max(j*dp[i-j],j*(i-j)),dp[i]);
//dp[i]可由他的前一个数字推导而来
//它的最大值有可能是j*(i-j)也可能是j*dp[i-j]
for(int i=3;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i]=Math.max(Math.max(j*dp[i-j],j*(i-j)),dp[i]);
}
}
return dp[n];
}
}
给你一个整数 n
,求恰由 n
个节点组成且节点值从 1
到 n
互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
解题思路:
这道题核心思路就是从1到当前数字左右可能的左右节点数量相加,例如
动态规划
1,dp数组含义
dp[i]代表以i个不同元素组成的二叉搜索树的个数是dp[i]
2,递推公式
从j=1开始遍历所有可能的结点
dp[i]+=dp[j-1]*dp[i-j]
这个可能有点难理解,假如我们求3
1 2 3
则有dp[3]= dp[0]*dp[2]+dp[1]*dp[1]+dp[2]*dp[0]
假如根节点是1,那么左边比他小的结点是0个,右边比他大的是两个,这样理解
3,初始化:
dp[0]=1,空节点也是符合条件的,并且也符合dp数组解释
4,遍历:
依旧是两层循环
完整代码:
class Solution {
public int numTrees(int n) {
//dp数组含义
//dp[i]从1~i为根节点的二叉搜索树的个数为dp[i]
//dp数组初始化
int[] dp=new int[n+1];
dp[0]=1;
//递推公式
//dp[i]应该等于分别以1,2,i为根节点所对应的左右字数的成绩之和
//例如:dp[3]=dp[0]*dp[2]+dp[1]*dp[1]+dp[2]*dp[2]
//二叉搜索树,所以我们考虑的是左右子树的数量
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i]+=dp[j-1]*dp[i-j];
}
}
return dp[n];
}
}
给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
01背包问题不是很能理解,看着难实际也是难,明天仔细思考思考
By 三条直线围墙!!!