力扣算法 62.不同路径 63. 不同路径 II 343. 整数拆分 96. 不同的二叉搜索树

学习内容

力扣算法

62.不同路径

63. 不同路径 II

343. 整数拆分

96. 不同的二叉搜索树

具体内容

62.不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

做题思路

将该题想象成一个二维数组,由于题目要求只能向下或向右移动一步,即当前该位置的路径数量是由上角的路径数量以及左边的路径数量相加得到

解题

class Solution {
	public static int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        //初始化
        for (int i = 0; i < m; i++) {
            dp[i][0] = 1;
        }
        for (int i = 0; i < n; i++) {
            dp[0][i] = 1;
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
}

63. 不同路径 II

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。

做题思路

该题与62题不同点在于,遇到障碍物则后面的路径都不能走,因为题目只要求每次只能向下或者向右移动一步,因此要对是否是障碍物加以判断

解题

class Solution {
    //该题目与不同路径类似,唯一不同的是 当遇到障碍物时为1 又因为只能往下或者往右走 因此遇到障碍物后后面的路就不能走
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        //判断起始位置是否有障碍物
        if(obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1){
            return 0;
        }
        //初始化
        for(int i = 0;i < m;i++){
            if(obstacleGrid[i][0] == 1){
                break;
            }
            dp[i][0] = 1;
        }

        for(int j = 0;j < n;j++){
            if(obstacleGrid[0][j] == 1){
                break;
            }
            dp[0][j] = 1;
        }

        for(int i = 1; i < m ;i++){
            for(int j = 1;j < n;j++){
                dp[i][j] = (obstacleGrid[i][j] == 0) ? dp[i][j-1] + dp[i-1][j]:0;
            } 
        }

        return dp[m-1][n-1];
    }
}

解答代码存在的疑问

为什么 要有dp[i][j] = (obstacleGrid[i][j] == 0) ? dp[i][j-1] + dp[i-1][j]:0
防止遍历到该位置出现了障碍物的情况,当该位置是障碍物时,那么想要通过该位置前往右下角的路径就没有了,因此为0

343. 整数拆分

给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。

返回 你可以获得的最大乘积 。

示例 1:

输入: n = 2 输出: 1 解释: 2 = 1 + 1, 1 × 1 = 1。

示例 2:

输入: n = 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

做题思路

分析例子:当n=10时。拆为1+9、2+8、3+7…;而1+9中的9,又可拆为1+8、2+7、3+6…等等。
因此可看出,求最大的和是将n拆分为A和B,确定好A,之后对后一个元素B进行拆分,从而不断比较取得最大值

解题

class Solution {
    public int integerBreak(int n) {
        //该题类似于求一个数C 先确定一个数A 将另一个数B不断拆分 从而获得另一个数B的最大值
        //之后A在不断往后确定值 求得B的最大值在拆分的同时也与A相乘 看哪个数最大B
        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(dp[i],Math.max(j*(i-j),j*dp[i-j]));
            }
        }

        return dp[n];
    }
}

96. 不同的二叉搜索树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例 1:

输入:n = 3 输出:5

示例 2:

输入:n = 1 输出:1

解题思路

分析例子:当n=1,输出1;n=2输出2;n=3输出5;
而当n=3时,二叉搜索数分别是由跟节点为1、2、3组成;

元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量
元素2为头结点搜索树的数量 =右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量
元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 *左子树有2个元素的搜索树数量
上述公式之所以可以知道左右节点的元素数量,是由于该题时二叉搜索数,对左右孩子的大小有条件,当n=3,而根节点为0,则左孩子要比根节点小,即只有0个元素;右孩子要比根节点大,即有2个元素

即通过推理可得,求i的二叉搜索树种树是求1到i的种树

解题

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++){
        	    //一共i个节点,对于根节点j时,左子树的节点个数为j-1,右子树的节点个数为i-j
        		dp[i]+=dp[j-1]*dp[i-j];
        	}
        }
        return dp[n];
   }
}        

你可能感兴趣的:(算法,leetcode,动态规划)