代码随想录算法训练营第41天 | 343、96

文章介绍了两道使用动态规划解决的算法问题,一个是求解正整数拆分以获得最大乘积,另一个是计算不同节点数的二叉搜索树的种类。动态规划在这两个问题中起到了简化复杂性的作用,通过定义状态转移方程,分别得出了解决方案。

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];
    }
}

总结

如果不是亲手写上去的,我真的很难相信这个简单的代码对应的是一道如此难想的题。不过这也从另一个角度说明了动态规划实在是一种很好的方式,可以使复杂的题目简单化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值