vault backup: 2026-06-10 11:19:43

This commit is contained in:
2026-06-10 11:19:43 +08:00
parent 788576ec4b
commit b9bc08ab2f
6 changed files with 391 additions and 209 deletions
@@ -76,17 +76,24 @@ $$dp[i] = \max(arr[i], \ dp[i-1] + arr[i])$$
**含义**:以第 i 个元素结尾的最大子数组和,要么是从头开始(只取 arr[i]),要么是接在之前的最大子数组后面。
```plaintext
function maxSubarraySum(arr, n):
dp = array of size n
dp[0] = arr[0]
maxSum = dp[0]
```cpp
#include <vector>
#include <algorithm>
using namespace std;
for i = 1 to n-1:
dp[i] = max(arr[i], dp[i-1] + arr[i])
maxSum = max(maxSum, dp[i])
int maxSubarraySum(vector<int>& arr) {
int n = arr.size();
vector<int> dp(n);
dp[0] = arr[0];
int maxSum = dp[0];
return maxSum
for (int i = 1; i < n; i++) {
dp[i] = max(arr[i], dp[i-1] + arr[i]); // 从头开始 or 接在前面
maxSum = max(maxSum, dp[i]);
}
return maxSum;
}
```
**解释**:对每个位置 i,我们做一个决策——是从当前位置重新开始子数组,还是接在前面的子数组后面。选择较大的那个作为 dp[i]。最后取所有 dp[i] 的最大值。
@@ -104,25 +111,30 @@ function maxSubarraySum(arr, n):
$$dp[i][j] = \max(dp[i-1][j], \ dp[i][j-1]) + matrix[i][j]$$
```plaintext
function maxMatrixPath(matrix, n):
dp = n x n matrix
dp[0][0] = matrix[0][0]
```cpp
#include <vector>
#include <algorithm>
using namespace std;
int maxMatrixPath(vector<vector<int>>& matrix, int n) {
vector<vector<int>> dp(n, vector<int>(n));
dp[0][0] = matrix[0][0];
// 填第一行(只能从左边来)
for j = 1 to n-1:
dp[0][j] = dp[0][j-1] + matrix[0][j]
for (int j = 1; j < n; j++)
dp[0][j] = dp[0][j-1] + matrix[0][j];
// 填第一列(只能从上面来)
for i = 1 to n-1:
dp[i][0] = dp[i-1][0] + matrix[i][0]
for (int i = 1; i < n; i++)
dp[i][0] = dp[i-1][0] + matrix[i][0];
// 填其余位置
for i = 1 to n-1:
for j = 1 to n-1:
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + matrix[i][j]
for (int i = 1; i < n; i++)
for (int j = 1; j < n; j++)
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + matrix[i][j];
return dp[n-1][n-1]
return dp[n-1][n-1];
}
```
**解释**:到达位置 (i,j) 只能从上方 (i-1,j) 或左方 (i,j-1) 来。取两者中较大的路径和,加上当前位置的值。边界条件是第一行和第一列只有一条路径。
@@ -137,15 +149,19 @@ $$f(n) = f(n-1) + f(n-2)$$
**解释**:到达第 n 阶的方法数 = 从第 n-1 阶走1步 + 从第 n-2 阶走2步。这是一个变体的 Fibonacci 数列。
```plaintext
function climbStairs(n):
if n <= 2: return n
dp = array of size n+1
dp[1] = 1
dp[2] = 2
for i = 3 to n:
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
```cpp
#include <vector>
using namespace std;
int climbStairs(int n) {
if (n <= 2) return n;
vector<int> dp(n + 1);
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++)
dp[i] = dp[i-1] + dp[i-2];
return dp[n];
}
```
> [!question] 爬楼梯和Fibonacci有什么关系?
@@ -155,15 +171,19 @@ function climbStairs(n):
用动态规划可以将 Fibonacci 从 O(2ⁿ) 优化到 O(n):
```plaintext
function fibDP(n):
if n <= 1: return n
dp = array of size n+1
dp[0] = 0
dp[1] = 1
for i = 2 to n:
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
```cpp
#include <vector>
using namespace std;
int fibDP(int n) {
if (n <= 1) return n;
vector<int> dp(n + 1);
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++)
dp[i] = dp[i-1] + dp[i-2];
return dp[n];
}
```
> [!tip] 进一步优化空间
@@ -179,18 +199,26 @@ function fibDP(n):
$$dp[i][j] = \begin{cases} dp[i-1][j-1] + 1 & \text{if } X[i] = Y[j] \\ \max(dp[i-1][j], \ dp[i][j-1]) & \text{if } X[i] \neq Y[j] \end{cases}$$
```plaintext
function LCS(X, Y, m, n):
dp = (m+1) x (n+1) matrix, all zeros
```cpp
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
for i = 1 to m:
for j = 1 to n:
if X[i] == Y[j]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
int LCS(string& X, string& Y, int m, int n) {
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
return dp[m][n]
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (X[i-1] == Y[j-1])
dp[i][j] = dp[i-1][j-1] + 1; // 字符匹配,LCS长度+1
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]); // 取两种情况的较大值
}
}
return dp[m][n];
}
```
**解释**:如果当前字符匹配,则 LCS 长度等于去掉这两个字符后的 LCS 长度加 1;如果不匹配,则取"去掉 X 的当前字符"和"去掉 Y 的当前字符"两种情况的较大值。