代码随想录算法训练营第三十三天 | 动规

45 阅读2分钟

LeetCode ### 62.不同路径

📖 考察点

动规

📖 题意理解

💡 解题思路

/**

  • 1.dp[i][j]代表到达m,n有多少种不同的路径
  • 2.dp[i][j] = dp[i-1][j]+dp[i][j-1]
  • 3.初始化第一行和第一列为1;
  • 4.便历顺序为从上到下,从左到右;
  • 5.举例验证 2*2 [[1,1],[1,2]]

*/

💻 代码实现

JavaScript

var uniquePaths = function (m, n) {
	let dp = new Array(m).fill(0).map(()=>new Array(n));
	for(let i = 0;i<m;i++){
		dp[i][0] = 1;
	}
	for(let j = 0;j<n;j++){
		dp[0][j] = 1;
	}
	for(let i = 1;i<m;i++){
		for(let j = 1;j<n;j++){
			dp[i][j] = dp[i-1][j]+dp[i][j-1]
		}
	}
	return dp[m][n];
};


LeetCode ### 63. 不同路径 II

📖 考察点

动规

📖 题意理解

💡 解题思路

/**

  • 1.dp[i][j]代表到达m,n有多少种不同的路径
  • 2.dp[i][j] = dp[i-1][j]+dp[i][j-1]
  • 3.初始化第一行和第一列为1;遇到石头结束
  • 4.便历顺序为从上到下,从左到右;不为石头的才赋值
  • 5.举例验证正确

*/

💻 代码实现

JavaScript

var uniquePathsWithObstacles = function (obstacleGrid) {
	const m = obstacleGrid.length;
	const n = obstacleGrid[0].length;
	const dp = Array(m)
		.fill()
		.map((item) => Array(n).fill(0));

	for (let i = 0; i < m && obstacleGrid[i][0] === 0; ++i) {
		dp[i][0] = 1;
	}

	for (let i = 0; i < n && obstacleGrid[0][i] === 0; ++i) {
		dp[0][i] = 1;
	}

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

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


LeetCode # 343. 整数拆分

📖 考察点

动规

📖 题意理解

💡 解题思路

/**

  • 五部曲
  • 1.dp[i] 代表 i差分成正整数的最大值
    1. dp[i] = Math.max(dp[i], dp[i - j] * j, (i - j) * j);
  • 3.初始化dp[2] = 1;
  • 4.从前往后便历 */

💻 代码实现

JavaScript

var integerBreak = function (n) {
	let dp = new Array(n + 1).fill(0);
	dp[2] = 1;
	for (let i = 3; i <= n; i++) {
		for (let j = 1; j <= i / 2; j++) {
			dp[i] = Math.max(dp[i], dp[i - j] * j, (i - j) * j);
		}
	}
	return dp[n];
};

LeetCode # 96.不同的二叉搜索树

📖 考察点

动规 卡特兰数公式

📖 题意理解

💡 解题思路

// G(n)=f(1)+f(2)+f(3)+f(4)+...+f(n) // 假设 n 个节点存在二叉排序树的个数是 G (n),令 f(i) 为以 i 为根的二叉搜索树的个数,则 // 当 i 为根节点时,其左子树节点个数为 i-1 个,右子树节点为 n-i,则 // f(i)=G(i−1)∗G(n−i)

// 综合两个公式可以得到 卡特兰数 公式 // G(n)=G(0)∗G(n−1)+G(1)∗(n−2)+...+G(n−1)∗G(0)

💻 代码实现

JavaScript

var numTrees = function(n) {
    const dp = 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]
};


const numTrees =(n) => {
   return combination(2 * n, n) / (n + 1);
};


function combination(m, k) {
    if (k < 0 || k > m) return 0;
    if (k === 0 || k === m) return 1;
    // 优化计算:C(m,k) = C(m, m-k),取较小的k减少乘法次数
    k = Math.min(k, m - k);
    let result = 1;
    for (let i = 1; i <= k; i++) {
        result = result * (m - k + i) / i;
    }
    return Math.round(result); // 确保整数结果
}