Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4d0d2fb

Browse files
leetcode
1 parent 9410ed6 commit 4d0d2fb

7 files changed

+666
-1
lines changed

‎cpp/leetcode/152.乘积最大子数组.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@
5353
// @lc code=start
5454
class Solution {
5555
public:
56-
// 与最大和类似,区别是负数后面还可以再乘负数得到正数,而正数也可以乘负数得到正数,而最大和最需要关注正数即可。
56+
// 这种dp题目,一般是分析某个位置要或丢两种选择怎么选,输出结果有两种模式:
57+
// 一种是维护一个全局最大值,每次循环比较更新(这道题用这种方式,因为可以取中间片段)
58+
// 另外一种是直接求dp[n]或者dp[0]的值
59+
// 与最大和类似,区别是负数后面还可以再乘负数得到正数,而正数也可以乘负数得到负数,而最大和最需要关注正数即可。
5760
// 因此可以用两个变量分别存正数最大值和负数最小值,每次循环判断当前值去更新这两个值,同时更新全局最大值
5861
int maxProduct(std::vector<int> &nums) {
5962
if (nums.empty()) {

‎cpp/leetcode/174.地下城游戏.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* @lc app=leetcode.cn id=174 lang=cpp
3+
*
4+
* [174] 地下城游戏
5+
*
6+
* https://leetcode.cn/problems/dungeon-game/description/
7+
*
8+
* algorithms
9+
* Hard (48.76%)
10+
* Likes: 728
11+
* Dislikes: 0
12+
* Total Accepted: 62.6K
13+
* Total Submissions: 128.4K
14+
* Testcase Example: '[[-2,-3,3],[-5,-10,1],[10,30,-5]]'
15+
*
16+
* table.dungeon, .dungeon th, .dungeon td {
17+
* ⁠ border:3px solid black;
18+
* }
19+
*
20+
* ⁠.dungeon th, .dungeon td {
21+
* ⁠ text-align: center;
22+
* ⁠ height: 70px;
23+
* ⁠ width: 70px;
24+
* }
25+
*
26+
* 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n
27+
* 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角
28+
* 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
29+
*
30+
* 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0
31+
* 或以下,他会立即死亡。
32+
*
33+
* 有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为
34+
* 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
35+
*
36+
* 为了尽快解救公主,骑士决定每次只 向右 或 向下 移动一步。
37+
*
38+
* 返回确保骑士能够拯救到公主所需的最低初始健康点数。
39+
*
40+
* 注意:任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。
41+
*
42+
*
43+
*
44+
* 示例 1:
45+
*
46+
*
47+
* 输入:dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
48+
* 输出:7
49+
* 解释:如果骑士遵循最佳路径:右 -> 右 -> 下 -> 下 ,则骑士的初始健康点数至少为
50+
* 7 。
51+
*
52+
* 示例 2:
53+
*
54+
*
55+
* 输入:dungeon = [[0]]
56+
* 输出:1
57+
*
58+
*
59+
*
60+
*
61+
* 提示:
62+
*
63+
*
64+
* m == dungeon.length
65+
* n == dungeon[i].length
66+
* 1 <= m, n <= 200
67+
* -1000 <= dungeon[i][j] <= 1000
68+
*
69+
*
70+
*/
71+
72+
#include <limits.h>
73+
#include <vector>
74+
using namespace std;
75+
76+
// @lc code=start
77+
class Solution {
78+
public:
79+
int calculateMinimumHP(vector<vector<int>> &dungeon) {
80+
// 粗看是dp题,从终点往回思考归纳出状态转移方程,输出一般有两种结果,1是终点/起点值,2是维护中间变量
81+
// 先看状态转移方程,倒数第二步可以是[n-1][n]或者[n][n-1]两种,应该选初始值更小的路径
82+
// 设dp[i][j]是从左上角走到i,j的最小初始值,
83+
// dp[i][j] = min(min(dp[i-1][j], dp[i][j-1]), sum(x,y))
84+
// dp还需要看走左上或者右上的sub来判断,没法做dp,可以考虑从后往前dp去掉sum这一项
85+
86+
// 设dp[i][j]是从i,j到终点所需最小初始值,
87+
// 对于终点,如果是正数取1,负数则取1-c[m][n],也就是max(1-c[m][n], 1)
88+
// 对于边界[m-1][n],dp=max(dp[m][n]-c[m][n], 1),(初始值最小也是1)
89+
// 其他dp[i][j] = max(min(dp[i+1][j], dp[i][j+1]) - c[i][j]), 1)
90+
// 为了将矩阵边界也统一到上式,可以将边界设置为max,那min的时候就会取到下或者右
91+
92+
int m = dungeon.size(), n = dungeon[0].size();
93+
vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
94+
dp[m - 1][n] = dp[m][n - 1] = 1; // dp[m-1][n-1] = max(1-dungeon[i][j], 1)
95+
for (int i = m - 1; i >= 0; i--) {
96+
for (int j = n - 1; j >= 0; j--) {
97+
dp[i][j] = max(min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j], 1);
98+
}
99+
}
100+
return dp[0][0];
101+
}
102+
};
103+
// @lc code=end

‎cpp/leetcode/207.课程表.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* @lc app=leetcode.cn id=207 lang=cpp
3+
*
4+
* [207] 课程表
5+
*
6+
* https://leetcode.cn/problems/course-schedule/description/
7+
*
8+
* algorithms
9+
* Medium (53.58%)
10+
* Likes: 1595
11+
* Dislikes: 0
12+
* Total Accepted: 297.9K
13+
* Total Submissions: 556K
14+
* Testcase Example: '2\n[[1,0]]'
15+
*
16+
* 你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
17+
*
18+
* 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
19+
* 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须
20+
* 先学习课程 bi 。
21+
*
22+
*
23+
* 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
24+
*
25+
*
26+
* 请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
27+
*
28+
*
29+
*
30+
* 示例 1:
31+
*
32+
*
33+
* 输入:numCourses = 2, prerequisites = [[1,0]]
34+
* 输出:true
35+
* 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
36+
*
37+
* 示例 2:
38+
*
39+
*
40+
* 输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
41+
* 输出:false
42+
* 解释:总共有 2 门课程。学习课程 1
43+
* 之前,你需要先完成​课程 0 ;并且学习课程 0
44+
* 之前,你还应先完成课程 1 。这是不可能的。
45+
*
46+
*
47+
*
48+
* 提示:
49+
*
50+
*
51+
* 1
52+
* 0
53+
* prerequisites[i].length == 2
54+
* 0 i, bi < numCourses
55+
* prerequisites[i] 中的所有课程对 互不相同
56+
*
57+
*
58+
*/
59+
60+
#include <deque>
61+
#include <vector>
62+
using namespace std;
63+
64+
// @lc code=start
65+
class Solution {
66+
public:
67+
// 检查图是否有环,可按dag执行一遍,如果未全执行完则有环
68+
bool canFinish(int numCourses, vector<vector<int>> &prerequisites) {
69+
if (numCourses <= 1) {
70+
return true;
71+
}
72+
vector<vector<int>> graph(numCourses, vector<int>(0)); // output
73+
vector<int> indegree(numCourses, 0);
74+
for (int i = 0; i < prerequisites.size(); i++) {
75+
graph[prerequisites[i][1]].push_back(prerequisites[i][0]);
76+
indegree[prerequisites[i][0]]++;
77+
}
78+
79+
deque<int> q;
80+
for (int i = 0; i < numCourses; i++) {
81+
if (indegree[i] < 1) {
82+
q.push_back(i);
83+
}
84+
}
85+
86+
int cnt = 0;
87+
while (!q.empty()) {
88+
int idx = q.front();
89+
q.pop_front();
90+
cnt++;
91+
for (int i = 0; i < graph[idx].size(); i++) {
92+
int j = graph[idx][i];
93+
indegree[j]--;
94+
if (indegree[j] <= 0) {
95+
q.push_back(j);
96+
};
97+
}
98+
}
99+
return cnt == numCourses;
100+
}
101+
};
102+
// @lc code=end
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* @lc app=leetcode.cn id=208 lang=cpp
3+
*
4+
* [208] 实现 Trie (前缀树)
5+
*
6+
* https://leetcode.cn/problems/implement-trie-prefix-tree/description/
7+
*
8+
* algorithms
9+
* Medium (71.92%)
10+
* Likes: 1454
11+
* Dislikes: 0
12+
* Total Accepted: 263.1K
13+
* Total Submissions: 365.7K
14+
* Testcase Example:
15+
* '["Trie","insert","search","search","startsWith","insert","search"]\n[[],["apple"],["apple"],["app"],["app"],["app"],["app"]]'
16+
*
17+
* Trie(发音类似 "try")或者说 前缀树
18+
* 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。
19+
*
20+
* 请你实现 Trie 类:
21+
*
22+
*
23+
* Trie() 初始化前缀树对象。
24+
* void insert(String word) 向前缀树中插入字符串 word 。
25+
* boolean search(String word) 如果字符串 word 在前缀树中,返回
26+
* true(即,在检索之前已经插入);否则,返回 false 。 boolean startsWith(String
27+
* prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true
28+
* ;否则,返回 false 。
29+
*
30+
*
31+
*
32+
*
33+
* 示例:
34+
*
35+
*
36+
* 输入
37+
* ["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
38+
* [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
39+
* 输出
40+
* [null, null, true, false, true, null, true]
41+
*
42+
* 解释
43+
* Trie trie = new Trie();
44+
* trie.insert("apple");
45+
* trie.search("apple"); // 返回 True
46+
* trie.search("app"); // 返回 False
47+
* trie.startsWith("app"); // 返回 True
48+
* trie.insert("app");
49+
* trie.search("app"); // 返回 True
50+
*
51+
*
52+
*
53+
*
54+
* 提示:
55+
*
56+
*
57+
* 1
58+
* word 和 prefix 仅由小写英文字母组成
59+
* insert、search 和 startsWith 调用次数 总计 不超过 3 * 10^4 次
60+
*
61+
*
62+
*/
63+
#include <string>
64+
#include <vector>
65+
using namespace std;
66+
67+
// @lc code=start
68+
class Trie {
69+
public:
70+
Trie() : children_(26), isEnd_(false) {}
71+
72+
void insert(string word) {
73+
auto node = this;
74+
for (auto c : word) {
75+
c -= 'a';
76+
if (node->children_[c] == nullptr) {
77+
node->children_[c] = new Trie();
78+
}
79+
node = node->children_[c];
80+
}
81+
node->isEnd_ = true;
82+
}
83+
84+
bool search(string word) {
85+
auto node = searchPrefix(word);
86+
return node != nullptr && node->isEnd_;
87+
}
88+
89+
bool startsWith(string prefix) { return searchPrefix(prefix) != nullptr; }
90+
91+
private:
92+
vector<Trie *> children_;
93+
bool isEnd_;
94+
95+
Trie *searchPrefix(string& prefix) {
96+
auto node = this;
97+
for (auto c : prefix) {
98+
c -= 'a';
99+
if (node->children_[c] == nullptr) {
100+
return nullptr;
101+
}
102+
node = node->children_[c];
103+
}
104+
return node;
105+
}
106+
};
107+
108+
/**
109+
* Your Trie object will be instantiated and called as such:
110+
* Trie* obj = new Trie();
111+
* obj->insert(word);
112+
* bool param_2 = obj->search(word);
113+
* bool param_3 = obj->startsWith(prefix);
114+
*/
115+
// @lc code=end

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /