343. 整数拆分
链接
文章链接
题目链接
第一想法
这道题,想了比较长的时间,dp数组的含义为和为i的最大乘积,递推公式为arr[i] = Math.max(arr[i], arr[i - j] * j),比较i-j的最大值乘以j的最大值和i的最大值之间的较大值,同时初始化dp[0]和dp[1]都应该为0,但是这个就有一个问题,如果通过递推公式让arr[2]=1,所以我又想了一个,
arr[i] = Math.max(arr[i], ~~(i / 2) * (i - ~~(i / 2)))
;判断当前数的平分后的乘积与当前数的最大值取大值,就能解决都为0这个缺陷了,代码:
function integerBreak(n: number): number {
let arr: number[] = new Array(n + 1).fill(0)//初始化
for (let i = 2; i <= n; i++) {
for (let j = 1; j <= i; j++) {
arr[i] = Math.max(arr[i], arr[i - j] * j) //递归方程
}
arr[i] = Math.max(arr[i], ~~(i / 2) * (i - ~~(i / 2)))//比较当前最大值与当前i平分后乘积之间去大值
}
return arr[n]
}
看完文章后的想法
文章的想法更好,比我自己想的更加清晰,dp数组的含义是不变的,但是递推公式是改变的,和为i的乘积的最大值在(i-j)*j与arr[i-j]*j
之间产生,原因为(i-j)*j
可以看成两个数的乘积arr[i-j]*j
可以看成多个数的乘积,所以只需要比较他们的大小就可以了,代码如下:
function integerBreak(n: number): number {
let arr: number[] = new Array(n + 1).fill(0)
for (let i = 2; i <= n; i++) {
for (let j = 1; j <= i; j++) {
arr[i] = Math.max(arr[i], arr[i - j] * j, (i - j) * j)
}
}
return arr[n]
}
思考
这道题文章的想法是比较好理解的,但是我的写法更快一点,因为我知道~~(i / 2) * (i - ~~(i / 2))
肯定比(i-j)*j
大,所以我最后才比较~~(i / 2) * (i - ~~(i / 2))
与arr[i]的大小
96. 不同的二叉搜索树
链接
文章链接
题目链接
第一想法
emmmm想出来,想的是dp[i]的含义是个数为i的搜索二叉树的个数,刚开始没看到是搜索二叉树,然后发现找不到递推公式,然后仔细读了下题,发现是搜索二叉树了,然后就想到新添加的节点肯定是根节点,所以只需要改变根节点的左右孩子就行了,所以递推公式就是dp[i] += dp[i - j - 1] * dp[j],dp[i - j - 1] 和 dp[j]是左右孩子的个数,这里要i-j-1
的原因是根节点占据一个节点数
function numTrees(n: number): number {
let dp: number[] = new Array(n + 1).fill(0)
dp[0] = 1 //初始化
dp[1] = 1 //初始化
for (let i = 2; i <= n; i++) {
for (let j = 0; j < i; j++) {
dp[i] += dp[i - j - 1] * dp[j]//递推公式
}
}
return dp[n]
}
看完文章后的想法
很好,想法是错的,但是居然代码是对的,我想法中的新添加的节点肯定是根节点这个想法是错误的,应该是不同头结点的数量和,例如n=3的情况,就是头结点是1、2、3的数量和,例如这张图:
通过这张图,递推公式就很容易推出来的,dp[i]+=d[j-i](左孩子)*d[i-j](右孩子),因为初始化为dp[0]=1,没有节点就默认有一种情况,所以代码如下:
function numTrees(n: number): number {
let dp: number[] = new Array(n + 1).fill(0)
dp[0] = 1
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j]
}
}
return dp[n]
}
思考
这道题的思路是有问题的,但是偶然做对了,核心思想就是要知道n个节点的搜索二叉树的个数是根节点为1-n的总和,知道这样代码就很容易就写出来了
今日总结
今天总共两道题,都有一定的难度,第一道题的思路有一定的偏差,而第二道题思路就是有问题的,所以对于动态规划的题还是得多加练习