动态规划✅
因数分解
如下,实现 calc 方法,可以将输入的数拆解为尽可能多的乘数,所有数相乘等于输入数。
/**
* @param {number} n 乘积
* @return {Array} 拆解后的乘数
* input: 7
* output: [7]
* input: 8
* output: [2, 2, 2]
* input: 24
* output: [2, 2, 2, 3]
*/
function calc (n) { }
爬楼梯
/**
* 爬楼 n 阶你, 每次可以爬 1 或 2 个台阶。有多少种不同的方法可以爬到楼顶
* 输入:2
* 输出:2
* 1. 1 步 + 1 步
* 2. 2 步
* 输入:3
* 输出:3
* 1. 1 步 + 1 步 + 1 步
* 2. 1 步 + 2 步
* 3. 2 步 + 1 步
*/
function climbStairs (n) {
}
答案
斐波那契数列
/**
* 斐波那契数列
* 输入:n = 5
* 输出:5
* 解释:斐波那契数列为 0, 1, 1, 2, 3, 5, 8, ...
*/
function fibonacci (n) {
}
答案
最长递增子序列
/**
* 最长递增子序列
* 输入:[10,9,2,5,3,7,101,18]
* 输出:4
* 解释:最长上升子序列是 [2,3,7,101],长度为 4
*/
function lengthOfLIS (nums) {
}
答案
延伸阅读
在 Vue 等框架的 diff 算法中,也会使用最长递增子序列来优化 diff 逻辑。其中 Vue 的最长递增子序列源码如下 getSequence
编辑距离
/**
* 编辑距离
* 输入:word1 = "horse", word2 = "ros"
* 输出:3
* 解释:
* horse -> rorse (将 'h' 替换为 'r')
* rorse -> rose (删除 'r')
* rose -> ros (删除 'e')
*/
function minDistance (word1, word2) {
}
答案
背包问题
/**
* 背包问题
* 输入:weights = [2, 3, 4, 5], values = [3, 4, 5, 6], capacity = 5
* 输出:7
* 解释:选择物品 1 (重量 2, 价值 3) 和物品 2 (重量 3, 价值 4),总价值 7
*/
function knapsack (weights, values, capacity) {
}
答案
路径规划
答案
核心概念 LeetCode 第 62 题(不同路径 / Unique Paths): 机器人位于一个 $m \times n$ 网格的左上角 $(0, 0)$,每次只能向右或向下移动一步,求到达右下角 $(m-1, n-1)$ 共有多少条不同的路径:
- 状态定义:设 $dp[i][j]$ 表示到达网格 $(i, j)$ 位置的不同路径数。
- 状态转移方程:由于只能从上方或左方到达该格,故 $dp[i][j] = dp[i - 1][j] + dp[i][j - 1]$。
- 边界条件:第一行与第一列的任意格子都只有 1 种走法(一直向右或一直向下),即 $dp[0][j] = 1, dp[i][0] = 1$。
- 空间优化(滚动数组):$dp[j]$ 仅依赖本行的左侧值和上一行的同列值,可用长度为 $n$ 的一维数组完成状态压缩。
代码实现(一维滚动数组最优解):
function uniquePaths (m, n) {
// 初始化一维 dp 数组,首行所有格子路径数均为 1
const dp = new Array(n).fill(1)
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
// 当前格子路径 = 原上一行同列值(dp[j]) + 本行左侧值(dp[j-1])
dp[j] = dp[j] + dp[j - 1]
}
}
return dp[n - 1]
}
// 验证
console.log(uniquePaths(3, 7)) // 28
console.log(uniquePaths(3, 2)) // 3
复杂度分析
- 时间复杂度:$O(m \times n)$,双重循环遍历网格。
- 空间复杂度:$O(n)$,仅需一行长度为 $n$ 的数组空间。
面试官视角
- 考查从基础的二维矩阵 DP 推导,下探到空间压缩降维(一维滚动数组)的能力;数学背景好的候选人还可指出利用组合数学公式
C(m+n-2, m-1) = (m+n-2)! / ((m-1)!(n-1)!)直接在 $O(\min(m, n))$ 时间内计算完成。
200. 岛屿数量**
- 难度:中等
- 考点:DFS、BFS
- 应用场景:图形处理、连通性问题
dfs
function numIslands (grid: string[][]): number {
if (grid.length === 0) return 0
const rows = grid.length
const cols = grid[0].length
let count = 0
// DFS遍历整个岛屿并标记
const dfs = (row: number, col: number) => {
// 边界检查或已访问(水域)
if (row < 0 || row >= rows || col < 0 || col >= cols || grid[row][col] === '0') {
return
}
grid[row][col] = '0'
// 四个方向DFS
dfs(row - 1, col) // 上
dfs(row + 1, col) // 下
dfs(row, col - 1) // 左
dfs(row, col + 1) // 右
}
// 遍历网格
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
if (grid[row][col] === '1') {
count++
dfs(row, col)
}
}
}
return count
}