62. 不同路径

题目描述

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

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

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

示例

输入:m = 3, n = 7
输出:28

解题思路

标准的动态规划

递推公式为dp[i][j] = dp[i - 1][j] + dp[i][j - 1]

class Solution {
    public 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 j = 0; j < n; j++) {
            dp[0][j] = 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 的整数数组 grid。一个机器人初始位于 左上角(即 grid[0][0])。机器人尝试移动到 右下角(即 grid[m - 1][n - 1])。机器人每次只能向下或者向右移动一步。

网格中的障碍物和空位置分别用 10 来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。

返回机器人能够到达右下角的不同路径数量。

测试用例保证答案小于等于 2 * 109

示例

输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右

解题思路

在上一题的基础上,增加判断条件,当前位置是石头,则不用更新

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length, n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        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++) {
                if (obstacleGrid[i][j] != 1) {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
}

343. 整数拆分

题目描述

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

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

示例

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

解题思路

dp[i]表示整数i的最大乘积。对于每个i,又能被拆分为ji - j

那么dp[i] = Math.max(dp[i], j * Math.max(i - j, dp[i - j]))

class Solution {
    public int integerBreak(int n) {
        int[] dp = new int[n + 1];
        dp[1] = 1;
        for (int i = 1; i <= n; i++) {
	          // 求dp[i]
            for (int j = 1; j <= i / 2; j++) {
                // 将 i 分为两个整数, j值固定, 另一个求 i - j和 dp[i - j]的最大值
                int temp = j * Math.max(i - j, dp[i - j]);
                dp[i] = Math.max(temp, dp[i]);
            }
        }
        return dp[n];
    }
}

96. 不同的二叉搜索树

题目描述

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

示例

输入:n = 3
输出:5

解题思路

左子树的节点数范围在[0, n - 1]。所以以左子树为标准求节点数从[1, n]的数量即可

class Solution {
    public int numTrees(int n) {
        // dp[i],含有i个节点的二叉搜索树数量
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {  // 节点数
            // 分类,以左子树为准 [0, i - 1]
            for (int j = 0; j < i; j++) {
                // 因为根节点要用一个,所以左子树j个, 右子树 i-j-1 个
                dp[i] += dp[j] * dp[i - j - 1];
            }
        }
        return dp[n];
    }
}