代码注释与详细思路
这是一个求解“腐烂橙子”问题的解决方案,思路是通过模拟腐烂的过程来计算最小时间。问题的目标是找出腐烂橙子传染所有新鲜橙子的最短时间,或者在无法感染所有新鲜橙子的情况下返回 -1。
代码实现:
class Solution {
// 方向数组,四个方向:右、下、上、左
int Directions[4][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
public:
int orangesRotting(vector<vector<int>>& grid) {
int n = grid.size(); // 获取网格的行数
int m = grid[0].size(); // 获取网格的列数
int fresh = 0; // 记录新鲜橙子的数量
vector<pair<int, int>> q; // 用来存储腐烂橙子的坐标
// 遍历网格,统计新鲜橙子数并找到腐烂橙子的初始坐标
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 1) { // 如果是新鲜橙子
fresh++;
} else if (grid[i][j] == 2) { // 如果是腐烂橙子
q.emplace_back(i, j); // 将腐烂橙子位置加入队列
}
}
}
int ans = 0; // 记录腐烂所需的时间
// 当队列非空且还有新鲜橙子时,继续腐烂过程
while (!q.empty() && fresh) {
ans++; // 每一轮腐烂处理后,时间增加1
vector<pair<int, int>> new_q; // 用来存储新一轮腐烂的橙子
// 遍历当前队列中的所有腐烂橙子
for (auto& [x, y] : q) {
// 遍历四个方向:右、下、上、左
for (auto& d : Directions) {
int i = d[0] + x; // 计算新位置的行坐标
int j = d[1] + y; // 计算新位置的列坐标
// 判断新位置是否在网格内并且是新鲜橙子
if (i >= 0 && j >= 0 && i < n && j < m && grid[i][j] == 1) {
fresh--; // 新鲜橙子变腐烂
new_q.emplace_back(i, j); // 加入新腐烂橙子的队列
grid[i][j] = 2; // 更新为腐烂橙子
}
}
}
q = move(new_q); // 更新队列,继续处理下一轮
}
// 如果还有新鲜橙子未腐烂,返回 -1;否则返回最小时间
return fresh ? -1 : ans;
}
};
q = move(new_q); 会 覆盖 q 的资源。
具体情况:
• 在 q = move(new_q); 这一行中,std::move(new_q) 会将 new_q 的资源(即 new_q 中的元素)转移到 q 中。
• move 不会拷贝 new_q 中的元素,而是把 new_q 的内部资源(如指向内存的指针)转移给 q。
• 结果:q 将拥有 new_q 原本所拥有的资源,而 new_q 的资源就变得不可用(通常是一个空容器或者一个处于“空状态”的容器)。
覆盖的具体效果:
• q 会变成一个包含 new_q 元素的新容器,new_q 中的元素会被“移动”到 q。
• 原本属于 new_q 的资源(如内部动态数组、指针等)会被转移到 q,这意味着 q 将接管这些资源,而 new_q 不再拥有它们。
• new_q 会变成一个空容器,或者处于未定义状态(例如,某些容器的容量可能会发生变化,但它的元素将无法再被访问)。
小结:
• q = move(new_q); 会覆盖 q 的资源,使得 q 拥有 new_q 的元素,同时 new_q 的资源将被“转移”走,变为空容器或者不再使用原有数据。
• 这样做的好处是避免了不必要的拷贝操作,提高了性能。
详细思路:
1. 问题分析:
• 我们有一个二维网格,其中有三种类型的格子:
• 0 表示空格
• 1 表示新鲜橙子
• 2 表示腐烂橙子
• 腐烂橙子会在 4 个方向上(上、下、左、右)将相邻的新鲜橙子感染成腐烂。每个腐烂橙子感染相邻的新鲜橙子需要 1 单位时间。
• 我们需要计算最少时间来让所有新鲜橙子都变成腐烂橙子。如果有任何新鲜橙子无法变腐烂,返回 -1。
2. 核心思路:
• 使用广度优先搜索(BFS)模拟腐烂过程。腐烂的橙子将传播到其相邻的格子,逐步感染新鲜橙子。每一轮 BFS 执行都对应 1 单位时间。
• 初始状态是所有腐烂的橙子进入队列,每次 BFS 都扩展相邻的新鲜橙子。
3. 详细步骤:
• 第一步:遍历网格,统计新鲜橙子数量并记录所有腐烂橙子的初始坐标。
• 第二步:使用队列存储腐烂橙子的坐标,进行广度优先搜索。在每一轮 BFS 中,腐烂的橙子会传播到周围的新鲜橙子。
• 第三步:每次 BFS 迭代结束后,时间增加 1,直到队列为空或者没有新鲜橙子可以腐烂。
• 第四步:如果有新鲜橙子未被腐烂,返回 -1;否则返回最小时间。
4. 运行步骤:
• 初始化:计算网格的行列数,统计新鲜橙子的数量并找到腐烂橙子的初始位置。
• 使用 BFS 模拟腐烂过程,每轮遍历腐烂橙子的 4 个方向,感染相邻的新鲜橙子,直到没有新鲜橙子可以感染。
• 返回腐烂完成的最小时间,或者如果有新鲜橙子无法腐烂则返回 -1。
复杂度分析:
• 时间复杂度:
• 假设网格的大小为 n * m,我们遍历整个网格两次:
1. 一次遍历用于统计新鲜橙子和腐烂橙子的初始状态(O(n * m))。
2. 一次 BFS 遍历,每个腐烂橙子最多会处理四个相邻的格子,因此时间复杂度是 O(n * m)。
• 总时间复杂度为 O(n * m)。
• 空间复杂度:
• 使用一个队列来存储腐烂橙子的坐标,最多存储所有腐烂橙子的位置,空间复杂度是 O(n * m)。
示例:
输入:
vector<vector<int>> grid = {
{2,1,1},
{1,1,0},
{0,1,1}
};
执行步骤:
1. 初始时,腐烂橙子的位置为 (0,0),新鲜橙子数量为 4。
2. 第 1 秒:(0,0) 腐烂橙子感染相邻的 (0,1) 和 (1,0)。
3. 第 2 秒:(0,1) 和 (1,0) 继续感染相邻的新鲜橙子。
4. 最终结果:所有新鲜橙子腐烂完毕,最小时间为 4 秒。
输出:
4