文章目录
- 动态规划
-
- 股票问题
-
- 121. 买卖股票的最佳时机 [数组] [股票] (动态规划)
- 122. 买卖股票的最佳时机Ⅱ [数组] [股票] (动态规划)
- 123. 买卖股票的最佳时机Ⅲ [数组] [股票] (动态规划)
- 188. 买卖股票的最佳时机Ⅳ [数组] [股票] (动态规划)
- 309. 买卖股票的最佳时机含冷冻期 [数组] [股票] (动态规划)
- 714. 买卖股票的最佳时机含手续费 [数组] [股票] (动态规划)
- 打家劫舍
-
- 198. 打家劫舍 [数组] [打劫] (动态规划)
- 213. 打家劫舍Ⅱ [数组] [打劫] (动态规划)
- 337. 打家劫舍III [数组] [打劫] (动态规划) (递归)
- 背包问题
-
- 322. 零钱兑换 [数组] [背包] (动态规划)
- 416. 分隔等和子集 [数组] [背包] (动态规划)
- 474. 一和零 [字符数组] [背包] (动态规划)
- 494. 目标和 [数组] [背包] (动态规划)
- 518. 零钱兑换Ⅱ [数组] [背包] (动态规划)
- 1049. 最后一块石头的重量 [数组] [背包] (动态规划)
- 编辑距离
-
- 72. 编辑距离 [字符串] [编辑距离] (动态规划)
- 583. 两个字符串的删除操作 [字符串] [编辑距离] (动态规划)
- 1312. 让字符串成为回文串的最少插入次数 [字符串] [编辑距离] [回文] (动态规划)
- 712. 两个字符串的最小 ASCII 删除和 [字符串] [编辑和] (动态规划)
- 子序列
-
- 53. 最大子数组和 [数组] [子序列] (动态规划)
- 139. 单词拆分 [字符串] [拼接] (动态规划)
- 300. 最长递增子序列 [数组] [子序列] (动态规划)
- 516. 最长回文子序列 [字符串] [子序列] [回文] (动态规划)
- 1143. 最长公共子序列 [字符串] [子序列] (动态规划)
- 路径和
-
- 64. 最小路径和 [矩阵] [路径和] (动态规划)
- 174. 地下城游戏 [矩阵] [路径和] (动态规划) (逆向)
- 787. K 站中转内最便宜的航班 [图] [K步最短路径] (动态规划) (bellman ford)
- 931. 下降路径最小和 [矩阵] [路径和] (动态规划) (扩展边界)
- 其他
-
- 140. 单词拆分Ⅱ [字符串] (动态规划) (递归)
- 514. 自由之路 [字符串] [操作次数] (动态规划)
- 贪心算法
-
- 区间重叠
-
- 252. 会议室 [区间数组] [重叠] (贪心)
- 253. 会议室Ⅱ [区间数组] [重叠] (贪心)
- 435. 无重叠区间 [区间数组] [重叠] (贪心)
- 452. 用最少数量的箭引爆气球 [区间数组] [重叠] (贪心)
- 1024. 视频拼接 [区间数组] [重叠] (贪心)
- 跳跃
-
- 45. 跳跃游戏II [数组] [跳跃] (贪心)
- 55. 跳跃游戏 [数组] [跳跃] (贪心)
动态规划
股票问题
121. 买卖股票的最佳时机 [数组] [股票] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
dp = vector<vector<int>>(n, vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < n; ++i) {
for (int j = 0; j < 2; ++j) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = max(dp[i - 1][1], - prices[i]);
}
}
return dp[n - 1][0];
}
};
122. 买卖股票的最佳时机Ⅱ [数组] [股票] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
dp = vector<vector<int>>(n, vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < n; ++i) {
for (int j = 0; j < 2; ++j) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
}
}
return dp[n - 1][0];
}
};
123. 买卖股票的最佳时机Ⅲ [数组] [股票] (动态规划)
class Solution {
private:
vector<vector<vector<int>>> dp;
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
int K = 2;
dp = vector<vector<vector<int>>>(n, vector<vector<int>>(K + 1, vector<int>(2)));
for (int k = 0; k <= K; ++k) {
dp[0][k][0] = 0;
dp[0][k][1] = -prices[0];
}
for (int i = 1; i < n; ++i) {
dp[i][0][0] = 0;
dp[i][0][1] = max(dp[i - 1][0][1], dp[i - 1][0][0] - prices[i]);
}
for (int i = 1; i < n; ++i) {
for (int k = 1; k <= K; ++k) {
dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k - 1][1] + prices[i]);
dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k][0] - prices[i]);
}
}
return dp[n - 1][K][0];
}
};
188. 买卖股票的最佳时机Ⅳ [数组] [股票] (动态规划)
class Solution {
private:
vector<vector<vector<int>>> dp;
public:
int maxProfit(int K, vector<int>& prices) {
int n = prices.size();
dp = vector<vector<vector<int>>>(n, vector<vector<int>>(K + 1, vector<int>(2)));
for (int i = 0; i <= K; ++i) {
dp[0][i][0] = 0;
dp[0][i][1] = -prices[0];
}
for (int i = 1; i < n; ++i) {
dp[i][0][0] = 0;
dp[i][0][1] = max(dp[i - 1][0][1], dp[i - 1][0][0] - prices[i]);
}
for (int i = 1; i < n; ++i) {
for (int k = 1; k <= K; ++k) {
dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k - 1][1] + prices[i]);
dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k][0] - prices[i]);
}
}
return dp[n - 1][K][0];
}
};
309. 买卖股票的最佳时机含冷冻期 [数组] [股票] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
dp = vector<vector<int>>(n, vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
if (n > 1) {
dp[1][0] = max(dp[0][0], dp[0][1] + prices[1]);
dp[1][1] = max(dp[0][1], -prices[1]);
}
for (int i = 2; i < n; ++i) {
for (int j = 0; j < 2; ++j) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 2][0] - prices[i]);
}
}
return dp[n - 1][0];
}
};
714. 买卖股票的最佳时机含手续费 [数组] [股票] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int maxProfit(vector<int>& prices, int fee) {
int n = prices.size();
dp = vector<vector<int>>(n, vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < n; ++i) {
for (int j = 0; j < 2; ++j) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
}
}
return dp[n - 1][0];
}
};
打家劫舍
198. 打家劫舍 [数组] [打劫] (动态规划)
class Solution {
private:
vector<int> dp;
public:
int rob(vector<int>& nums) {
int n = nums.size();
dp = vector<int>(n, 0);
dp[0] = nums[0];
if (n > 0) {
dp[1] = max(dp[0], nums[1]);
}
for (int i = 2; i < n; ++i) {
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);
}
return dp[n - 1];
}
};
213. 打家劫舍Ⅱ [数组] [打劫] (动态规划)
class Solution {
private:
vector<int> dp1, dp2;
public:
int rob(vector<int>& nums) {
int n = nums.size();
if (n == 1) return nums[0];
if (n == 2) return max(nums[0], nums[1]);
dp1 = vector<int>(n - 1, 0);
dp2 = vector<int>(n - 1, 0);
dp1[0] = nums[0];
dp1[1] = max(dp1[0], nums[1]);
dp2[0] = nums[1];
dp2[1] = max(dp2[0], nums[2]);
for (int i = 2; i < n - 1; ++i) {
dp1[i] = max(dp1[i - 1], dp1[i - 2] + nums[i]);
}
for (int i = 2; i < n - 1; ++i) {
dp2[i] = max(dp2[i - 1], dp2[i - 2] + nums[i + 1]);
}
return max(dp1[n - 2], dp2[n - 2]);
}
};
337. 打家劫舍III [数组] [打劫] (动态规划) (递归)
class Solution {
private:
unordered_map<TreeNode*, int> dp;
public:
int rob(TreeNode* root) {
return traverse(root);
}
int traverse(TreeNode* root) {
if (root == nullptr) return 0;
if (dp.count(root)) return dp[root];
int q1 = root->val;
if (root->left != nullptr) {
q1 += traverse(root->left->left) + traverse(root->left->right);
}
if (root->right != nullptr) {
q1 += traverse(root->right->left) + traverse(root->right->right);
}
int q2 = 0;
q2 += traverse(root->left) + traverse(root->right);
dp[root] = max(q1, q2);
return dp[root];
}
};
背包问题
322. 零钱兑换 [数组] [背包] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int coinChange(vector<int>& coins, int amount) {
if (amount == 0) return 0;
int n = coins.size();
dp = vector<vector<int>>(n + 1, vector<int>(amount + 1, INT_MAX - 1));
dp[0][0] = 0;
for (int i = 1; i <= n; ++i) {
int cur = coins[i - 1];
for (int j = 0; j <= amount; ++j) {
if (cur <= j) {
dp[i][j] = min(dp[i - 1][j], dp[i][j - cur] + 1);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n][amount] == INT_MAX - 1 ? -1 : dp[n][amount];
}
};
416. 分隔等和子集 [数组] [背包] (动态规划)
class Solution {
private:
vector<vector<bool>> dp;
public:
bool canPartition(vector<int>& nums) {
int n = nums.size();
int sum = 0;
for (int i = 0; i < n; ++i) {
sum += nums[i];
}
if (sum % 2 == 1) return false;
int target = sum / 2;
dp = vector<vector<bool>>(n + 1, vector<bool>(target + 1, false));
for (int i = 0; i <= n; ++i) {
dp[i][0] = true;
}
for (int i = 1; i <= n; ++i) {
int cur = nums[i - 1];
for (int j = 1; j <= target; ++j) {
if (cur == j) {
dp[i][j] = true;
} else if (cur > j) {
dp[i][j] = dp[i - 1][j];
} else if (cur < j) {
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - cur];
}
}
}
return dp[n][target];
}
};
474. 一和零 [字符数组] [背包] (动态规划)
class Solution {
private:
vector<vector<vector<int>>> dp;
public:
int findMaxForm(vector<string>& strs, int m, int n) {
int len = strs.size();
dp = vector<vector<vector<int>>>(len + 1, vector<vector<int>>(m + 1, vector<int>(n + 1, 0)));
for (int i = 1; i <= len; ++i) {
pair<int, int> getZO = count(strs[i - 1]);
int zeros = getZO.first, ones = getZO.second;
for (int j = 0; j <= m; ++j) {
for (int k = 0; k <= n; ++k) {
if (zeros <= j && ones <= k) {
dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - zeros][k - ones] + 1);
} else {
dp[i][j][k] = dp[i - 1][j][k];
}
}
}
}
return dp[len][m][n];
}
pair<int, int> count(string& str) {
int zeros = 0, ones = 0;
for (auto ch : str) {
if (ch == '0') {
zeros++;
} else {
ones++;
}
}
return make_pair(zeros, ones);
}
};
494. 目标和 [数组] [背包] (动态规划)
class Solution {
private:
vector<int> dp;
public:
int findTargetSumWays(vector<int>& nums, int target) {
int n = nums.size();
int total = 0;
for (int i = 0; i < n; ++i) {
total += nums[i];
}
if (abs(target) > total) return 0;
if ((total + target) % 2 == 1) return 0;
int pos = (total + target) / 2;
dp = vector<int>(pos + 1, 0);
dp[0] = 1;
for (int i = 1; i <= n; ++i) {
int cur = nums[i - 1];
for (int j = pos; j >= 0; --j) {
if (cur <= j) {
dp[j] = dp[j] + dp[j - cur];
}
}
}
return dp[pos];
}
};
518. 零钱兑换Ⅱ [数组] [背包] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int change(int amount, vector<int>& coins) {
int n = coins.size();
dp = vector<vector<int>>(n + 1, vector<int>(amount + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; ++i) {
int coin = coins[i - 1];
for (int j = 0; j <= amount; ++j) {
if (coin <= j) {
dp[i][j] = dp[i - 1][j] + dp[i][j - coin];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n][amount];
}
};
1049. 最后一块石头的重量 [数组] [背包] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int lastStoneWeightII(vector<int>& stones) {
int n = stones.size();
int sum = 0;
for (auto& stone : stones) {
sum += stone;
}
dp = vector<vector<int>>(n + 1, vector<int>(sum / 2 + 1, 0));
for (int i = 1; i <= n; ++i) {
int stone = stones[i - 1];
for (int j = 0; j <= sum / 2; ++j) {
if (stone <= j) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - stone] + stone);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return sum - 2 * dp[n][sum / 2];
}
};
编辑距离
72. 编辑距离 [字符串] [编辑距离] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
dp = vector<vector<int>>(m + 1, vector<int>(n + 1, 0));
for (int i = 0; i <= m; ++i) dp[i][0] = i;
for (int j = 0; j <= n; ++j) dp[0][j] = j;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
}
}
}
return dp[m][n];
}
};
583. 两个字符串的删除操作 [字符串] [编辑距离] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
dp = vector<vector<int>>(m + 1, vector<int>(n + 1, 0));
for (int i = 0; i <= m; ++i) dp[i][0] = i;
for (int j = 0; j <= n; ++j) dp[0][j] = j;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1;
}
}
}
return dp[m][n];
}
};
1312. 让字符串成为回文串的最少插入次数 [字符串] [编辑距离] [回文] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int minInsertions(string s) {
int n = s.size();
dp = vector<vector<int>>(n, vector<int>(n, 0));
for (int len = 2; len <= n; ++len) {
for (int i = 0; i <= n - len; ++i) {
int j = i + len -1;
if (s[i] == s[j]) {
dp[i][j] = dp[i + 1][j - 1];
} else {
dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
}
}
}
return dp[0][n - 1];
}
};
712. 两个字符串的最小 ASCII 删除和 [字符串] [编辑和] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int minimumDeleteSum(string s1, string s2) {
int m = s1.size(), n = s2.size();
dp = vector<vector<int>>(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; ++i) dp[i][0] = dp[i - 1][0] + s1[i - 1];
for (int j = 1; j <= n; ++j) dp[0][j] = dp[0][j - 1] + s2[j - 1];
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (s1[i - 1] == s2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = min(dp[i - 1][j] + s1[i - 1], dp[i][j - 1] + s2[j - 1]);
}
}
}
return dp[m][n];
}
};
子序列
53. 最大子数组和 [数组] [子序列] (动态规划)
class Solution {
private:
vector<int> dp;
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
dp = vector<int>(n, 0);
dp[0] = nums[0];
for (int i = 1; i < n; ++i) {
dp[i] = max(nums[i], nums[i] + dp[i - 1]);
}
int res = *max_element(dp.begin(), dp.end());
return res;
}
};
139. 单词拆分 [字符串] [拼接] (动态规划)
class Solution {
private:
vector<bool> dp;
unordered_set<string> uset;
public:
bool wordBreak(string s, vector<string>& wordDict) {
int n = s.size();
dp = vector<bool>(n + 1, false);
for (auto& word : wordDict) {
uset.insert(word);
}
dp[0] = true;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < i; ++j) {
if (dp[j] && uset.count(s.substr(j, i - j))) {
dp[i] = true;
break;
}
}
}
return dp[n];
}
};
300. 最长递增子序列 [数组] [子序列] (动态规划)
class Solution {
private:
vector<int> dp;
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
dp = vector<int>(n, 1);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
int res = *max_element(dp.begin(), dp.end());
return res;
}
};
516. 最长回文子序列 [字符串] [子序列] [回文] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int longestPalindromeSubseq(string s) {
int n = s.size();
dp = vector<vector<int>>(n, vector<int>(n, 0));
for (int i = 0; i < n; ++i) dp[i][i] = 1;
for (int len = 2; len <= n; ++len) {
for (int i = 0; i <= n - len; ++i) {
int j = i + len - 1;
if (s[i] == s[j]) {
dp[i][j] = dp[i + 1][j - 1] + 2;
} else {
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][n - 1];
}
};
1143. 最长公共子序列 [字符串] [子序列] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.size(), n = text2.size();
dp = vector<vector<int>>(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (text1[i - 1] == text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
}
}
}
return dp[m][n];
}
};
路径和
64. 最小路径和 [矩阵] [路径和] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
public:
int minPathSum(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
dp = vector<vector<int>>(m, vector<int>(n, 0));
dp[0][0] = grid[0][0];
for (int i = 1; i < m; ++i) dp[i][0] = dp[i - 1][0] + grid[i][0];
for (int j = 1; j < n; ++j) dp[0][j] = dp[0][j - 1] + grid[0][j];
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[m - 1][n - 1];
}
};
174. 地下城游戏 [矩阵] [路径和] (动态规划) (逆向)
class Solution {
private:
vector<vector<int>> dp;
public:
int calculateMinimumHP(vector<vector<int>>& dungeon) {
int m = dungeon.size(), n = dungeon[0].size();
dp = vector<vector<int>>(m, vector<int>(n, 0));
dp[m - 1][n - 1] = max(1, 1 - dungeon[m - 1][n - 1]);
for (int i = m - 2; i >= 0; --i) {
dp[i][n - 1] = max(1, dp[i + 1][n - 1] - dungeon[i][n - 1]);
}
for (int i = n - 2; i >= 0; --i) {
dp[m - 1][i] = max(1, dp[m - 1][i + 1] - dungeon[m - 1][i]);
}
for (int i = m - 2; i >= 0; --i) {
for (int j = n - 2; j >= 0; --j) {
dp[i][j] = max(1, min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);
}
}
return dp[0][0];
}
};
787. K 站中转内最便宜的航班 [图] [K步最短路径] (动态规划) (bellman ford)
class Solution {
private:
vector<vector<int>> dp;
const int INF = 0x3f3f3f3f;
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
dp = vector<vector<int>>(k + 2, vector<int>(n, INF));
dp[0][src] = 0;
for (int i = 1; i <= k + 1; ++i) {
for (auto& flight : flights) {
int start = flight[0], end = flight[1], cost = flight[2];
dp[i][end] = min(dp[i][end], dp[i - 1][start] + cost);
}
}
int res = INF;
for (int i = 1; i <= k + 1; ++i) {
res = min(res, dp[i][dst]);
}
return res == INF ? -1 : res;
}
};
931. 下降路径最小和 [矩阵] [路径和] (动态规划) (扩展边界)
class Solution {
private:
vector<vector<int>> dp;
vector<vector<int>> dirts = {{-1, -1}, {-1, 0}, {-1, 1}};
public:
int minFallingPathSum(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size();
dp = vector<vector<int>>(m, vector<int>(n + 2, INT_MAX));
for (int j = 1; j <= n; ++j) dp[0][j] = matrix[0][j - 1];
for (int i = 1; i < m; ++i) {
for (int j = 1; j <= n; ++j) {
for (auto& dirt : dirts) {
dp[i][j] = min(dp[i][j], dp[i + dirt[0]][j + dirt[1]]);
}
dp[i][j] += matrix[i][j - 1];
}
}
int res = *min_element(dp[m - 1].begin(), dp[m - 1].end());
return res;
}
};
其他
140. 单词拆分Ⅱ [字符串] (动态规划) (递归)
class Solution {
private:
unordered_set<string> uset;
vector<vector<string>> dp;
int n;
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
int n = s.size(); this->n = n;
dp = vector<vector<string>>(n, vector<string>(0));
for (auto& word : wordDict) {
uset.insert(word);
}
vector<int> res = traverse(s, 0);
return res;
}
vector<string> traverse(string s, int i) {
vector<string> cur_res;
if (i == n) {
cur_res.push_back("");
return cur_res;
}
if (!dp[i].empty()) {
return dp[i];
}
for (int len = 1; len + i <= n; ++len) {
string subStr = s.substr(i, len);
if (uset.count(subStr)) {
vector<string> subFind = traverse(s, i + len);
for (auto& sub : subFind) {
if (sub.empty()) {
cur_res.push_back(subStr);
} else {
cur_res.push_back(subStr + " " + sub);
}
}
}
}
dp[i] = cur_res;
return cur_res;
}
};
514. 自由之路 [字符串] [操作次数] (动态规划)
class Solution {
private:
vector<vector<int>> dp;
unordered_map<char, vector<int>> umap;
public:
int findRotateSteps(string ring, string key) {
int m = key.size(), n = ring.size();
dp = vector<vector<int>>(m, vector<int>(n, INT_MAX));
for (int i = 0; i < n; ++i) {
umap[ring[i]].push_back(i);
}
for (auto& pos : umap[key[0]]) {
dp[0][pos] = min(dp[0][pos], cal(n, 0, pos) + 1);
}
for (int i = 1; i < m; ++i) {
for (auto& pos : umap[key[i]]) {
for (auto& prepos : umap[key[i - 1]]) {
dp[i][pos] = min(dp[i][pos], dp[i - 1][prepos] + cal(n, prepos, pos) + 1);
}
}
}
int res = *min_element(dp[m - 1].begin(), dp[m - 1].end());
return res;
}
int cal(int len, int a, int b) {
return min((len + a - b) % len, (len + b - a) % len);
}
};
贪心算法
区间重叠
252. 会议室 [区间数组] [重叠] (贪心)
class Solution {
private:
int cur_end = INT_MIN;
public:
bool canAttendMeetings(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b) {
return a[1] < b[1];
});
for (auto& interval : intervals) {
int start = interval[0], end = interval[1];
if (start < cur_end) return false;
cur_end = end;
}
return true;
}
};
253. 会议室Ⅱ [区间数组] [重叠] (贪心)
class Solution {
private:
vector<int> start;
vector<int> end;
int res= 0, count = 0;
public:
int minMeetingRooms(vector<vector<int>>& intervals) {
int n = intervals.size();
for (auto& interval : intervals) {
start.push_back(interval[0]);
end.push_back(interval[1]);
}
sort(start.begin(), start.end());
sort(end.begin(), end.end());
int i = 0, j = 0;
while (i < n) {
if (start[i] < end[j]) {
count++;
i++;
} else {
count--;
j++;
}
res = max(res, count);
}
return res;
}
};
435. 无重叠区间 [区间数组] [重叠] (贪心)
class Solution {
private:
int count = 0;
int cur_end = INT_MIN;
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b) {
return a[1] < b[1];
});
for (auto& interval : intervals) {
int start = interval[0], end = interval[1];
if (start < cur_end) {
count++;
continue;
}
cur_end = end;
}
return count;
}
};
452. 用最少数量的箭引爆气球 [区间数组] [重叠] (贪心)
class Solution {
private:
int res = 0;
long cur_end = LONG_MIN;
public:
int findMinArrowShots(vector<vector<int>>& points) {
sort (points.begin(), points.end(), [](vector<int>& a, vector<int>& b) {
return a[1] < b[1];
});
for (auto& point : points) {
int start = point[0], end = point[1];
if (start <= cur_end) continue;
res++;
cur_end = end;
}
return res;
}
};
1024. 视频拼接 [区间数组] [重叠] (贪心)
class Solution {
private:
int res = 0;
public:
int videoStitching(vector<vector<int>>& clips, int time) {
int n = clips.size();
sort(clips.begin(), clips.end(), [](vector<int>& a, vector<int>& b) {
if (a[0] == b[0]) return a[1] > b[1];
return a[0] < b[0];
});
if (clips[0][0] != 0) return -1;
if (n == 1 && clips[0][1] != time) return -1;
int cur_end = 0, next_end = 0;
int i = 0;
while (i < n && clips[i][0] <= cur_end) {
while (i < n && clips[i][0] <= cur_end) {
next_end = max(next_end, clips[i][1]);
i++;
}
res++;
cur_end = next_end;
if (cur_end >= time) return res;
}
return -1;
}
};
跳跃
45. 跳跃游戏II [数组] [跳跃] (贪心)
class Solution {
public:
int jump(vector<int>& nums) {
int n = nums.size();
int end = 0;
int jump = 0;
int far = 0;
for (int i = 0; i < n - 1; ++i) {
far = max(far, i + nums[i]);
if (i == end) {
jump++;
end = far;
}
}
return jump;
}
};
55. 跳跃游戏 [数组] [跳跃] (贪心)
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
int far = 0;
for (int i = 0; i < n - 1; ++i) {
far = max(far, i + nums[i]);
if (far <= i) return false;
}
if (far < n - 1) return false;
return true;
}
};