目录
一,01矩阵
二,腐烂的橘子
观察到对于所有的腐烂橘子,其实它们在广度优先搜索上是等价于同一层的节点的。
假设这些腐烂橘子刚开始是新鲜的,而有一个腐烂橘子(我们令其为超级源点)会在下一秒把这些橘子都变腐烂,而这个腐烂橘子刚开始在的时间是 −1 ,那么按照广度优先搜索的算法,下一分钟也就是第 0 分钟的时候,这个腐烂橘子会把它们都变成腐烂橘子,然后继续向外拓展,所以其实这些腐烂橘子是同一层的节点。那么在广度优先搜索的时候,我们将这些腐烂橘子都放进队列里进行广度优先搜索即可,最后每个新鲜橘子被腐烂的最短时间 dis[x][y] 其实是以这个超级源点的腐烂橘子为起点的广度优先搜索得到的结果。
为了确认是否所有新鲜橘子都被腐烂,可以记录一个变量 cnt 表示当前网格中的新鲜橘子数,广度优先搜索的时候如果有新鲜橘子被腐烂,则 cnt-=1 ,最后搜索结束时如果 cnt 大于 0 ,说明有新鲜橘子没被腐烂,返回 −1 ,否则返回所有新鲜橘子被腐烂的时间的最大值即可,也可以在广度优先搜索的过程中把已腐烂的新鲜橘子的值由 1 改为 2,最后看网格中是否由值为 1 即新鲜的橘子即可。
- class Solution {
- int cnt;
- int dis[10][10];
- int dir_x[4]={0, 1, 0, -1};
- int dir_y[4]={1, 0, -1, 0};
- public:
- int orangesRotting(vector<vector<int>>& grid) {
- queue<pair<int,int> >Q;
- memset(dis, -1, sizeof(dis));
- cnt = 0;
- int n=(int)grid.size(), m=(int)grid[0].size(), ans = 0;
- for (int i = 0; i < n; ++i){
- for (int j = 0; j < m; ++j){
- if (grid[i][j] == 2){
- Q.push(make_pair(i, j));
- dis[i][j] = 0;
- }
- else if (grid[i][j] == 1) cnt += 1;
- }
- }
- while (!Q.empty()){
- pair<int,int> x = Q.front();Q.pop();
- for (int i = 0; i < 4; ++i){
- int tx = x.first + dir_x[i];
- int ty = x.second + dir_y[i];
- if (tx < 0|| tx >= n || ty < 0|| ty >= m|| ~dis[tx][ty] || !grid[tx][ty]) continue;
- dis[tx][ty] = dis[x.first][x.second] + 1;
- Q.push(make_pair(tx, ty));
- if (grid[tx][ty] == 1){
- cnt -= 1;
- ans = dis[tx][ty];
- if (!cnt) break;
- }
- }
- }
- return cnt ? -1 : ans;
- }
- };
时间复杂度:O(nm)
即进行一次广度优先搜索的时间,其中n=grid.length, m=grid[0].length 。
空间复杂度:O(nm)
需要额外的 dis 数组记录每个新鲜橘子被腐烂的最短时间,大小为 O(nm),且广度优先搜索中队列里存放的状态最多不会超过nm 个,最多需要 O(nm) 的空间,所以最后的空间复杂度为 O(nm)。