vault backup: 2026-06-10 11:19:43
This commit is contained in:
+77
-49
@@ -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 的当前字符"两种情况的较大值。
|
||||
|
||||
Reference in New Issue
Block a user