LeetCode Hot100 Graph

岛屿数量

Problem

https://leetcode.cn/problems/number-of-islands/description/?envType=study-plan-v2&envId=top-100-liked

Solution

遍历二维数组,找到为1的点,从这个点开始深度优先搜索将遇到的所有1置0,为1的起点数量即为岛屿数量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public:

void dfs(vector<vector<char>> &grid, int start_i, int start_j)
{
if (start_i < 0 || start_i >= grid.size() || start_j < 0 || start_j >= grid[0].size())
return;
if (grid[start_i][start_j] == '0') return;
grid[start_i][start_j] = '0';

for (int k = 0; k < 4; k ++)
{
int x = k < 2 ? (k % 2 ? 1 : -1) : 0;
int y = k < 2 ? 0 : (k % 2 ? 1 : -1);

dfs(grid, start_i + x, start_j + y);
}
}

int numIslands(vector<vector<char>>& grid) {

int m = grid.size();
int n = grid[0].size();
int ans = 0;
for (int i = 0; i < m; i ++)
{
for (int j = 0; j < n; j ++)
{
if (grid[i][j] == '1')
{
dfs(grid, i, j);
ans ++;
}
}
}
return ans;
}
};

腐烂的橘子

Problem

https://leetcode.cn/problems/rotting-oranges/?envType=study-plan-v2&envId=top-100-liked

Solution

首先遍历网格,将腐烂的橘子进队并统计新鲜橘子的数量,广度优先搜索,每分钟将当前队列的腐烂橘子出队,并将周围的新鲜橘子感染进队,直到队列为空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class Solution {
public:

int orangesRotting(vector<vector<int>>& grid) {
int m = grid.size();
int n = grid[0].size();

queue<int> bad_queue;

int good_count = 0;
for (int i = 0; i < m; i ++)
{
for (int j = 0; j < n; j ++)
{
if (grid[i][j] == 2)
{
bad_queue.push((i * n + j));
}
else if (grid[i][j] == 1)
{
good_count ++;
}
}
}
if (good_count == 0) return 0;

if (bad_queue.empty()) return -1;
int ans = 0;

while (!bad_queue.empty())
{
int size = bad_queue.size();
bool flag = false;
for (int c = 0; c < size; c ++)
{
int idx = bad_queue.front();
bad_queue.pop();

int i = idx / n, j = idx % n;

for (int x = 0; x < 4; x ++)
{
int di = i + (x < 2 ? (x % 2 ? -1 : 1) : 0);
int dj = j + (x < 2 ? 0 : (x % 2 ? -1 : 1));

if (di >= 0 && di < m && dj >= 0 && dj < n)
{
if (grid[di][dj] == 1)
{
grid[di][dj] = 2;
bad_queue.push((di * n + dj));
flag = true;
good_count --;
}
}
}
}
if (flag)
ans ++;
}

return good_count == 0 ? ans : -1;
}
};

课程表

Problem

https://leetcode.cn/problems/course-schedule/?envType=study-plan-v2&envId=top-100-liked

Solution

首先根据prerequisites建图,图节点就是0~numCourse-1,图边代表结点间控制关系,记录各个节点入度。节点入度为0代表这节课能上了。
遍历图,将入度为0的节点入队,该节点出队时将其控制节点入度-1,若被控制节点入度为0则入队等待处理。处理过程中记录出队节点数量,即为能上的课程数量,能上的课程数量等于课程总数即可能完成所有课程的学习。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {

vector<vector<int>> edges(numCourses);
vector<int> indegrees(numCourses, 0);

for (const std::vector<int> &edge : prerequisites)
{
edges[edge[1]].push_back(edge[0]);
indegrees[edge[0]] ++;
}

queue<int> ready_course;

for (int i = 0; i < numCourses; i ++)
{
if (indegrees[i] == 0)
{
ready_course.push(i);
}
}

int ready_count = 0;
while (!ready_course.empty())
{
int front = ready_course.front();
ready_course.pop();
ready_count ++;
for (int end : edges[front])
{
indegrees[end] --;
if (indegrees[end] == 0)
{
ready_course.push(end);
}
}
}
return ready_count == numCourses;
}
};

Tire前缀树

Problem

https://leetcode.cn/problems/implement-trie-prefix-tree/?envType=study-plan-v2&envId=top-100-liked

Solution

前缀树,树节点有26个指针(每个指针依次指向字母后继字母是’a’-‘z’的节点,为空代表没有这个字母)和一个是否为单词最后一个字母的标志位,插入的时候按照字符串中字母顺序建树,要注意若某孩子指针不为空,不需要新建节点。搜索的时候按照字母序列遍历该树若遇到空节点或者最后一个字母不是单词的最后一个字母,说明不存在这个单词,否则存在。前缀匹配时按照字母序列遍历该树,若遇到空节点说明匹配失败,否则匹配成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Trie {
public:
bool is_end = false;
vector<Trie *> children;
Trie() : children(26, nullptr) {

}

void insert(string word) {
Trie *pre = this;
for (char c : word)
{
if (pre->children[c-'a'] == nullptr)
pre->children[c-'a'] = new Trie();
pre = pre->children[c-'a'];
}
pre->is_end = true;
}

bool search(string word) {
Trie *pre = this;
for (char c : word)
{
if (pre->children[c-'a'] == nullptr)
return false;
pre = pre->children[c-'a'];
}
return pre->is_end;
}

bool startsWith(string prefix) {
Trie *pre = this;
for (char c : prefix)
{
if (pre->children[c-'a'] == nullptr)
return false;
pre = pre->children[c-'a'];
}
return true;
}
};

/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/