一、环境说明
- 本文是 LeetCode 994题 : 腐烂的橘子,使用c语言实现
- 模拟广度优先遍历。
- 测试环境:Visual Studio 2019
二、代码展示
typedef struct queue{
int x;
int y;
}queue;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
int orangesRotting(int** grid, int gridSize, int* gridColSize) {
int m = gridSize;
int n = gridColSize[0];
int** dis = (int**)calloc(m, sizeof(int*));
for (int i = 0; i < m; i++) {
dis[i] = (int*)calloc(n, sizeof(int));
memset(&dis[i][0], -1, n * sizeof(int));
}
queue* q = (queue*)calloc(m * n, sizeof(queue));
int front = 0, rear = 0, cnt = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (2 == grid[i][j]) {
q[rear].x = i;
q[rear++].y = j;
dis[i][j] = 0;
}
else if (1 == grid[i][j]) {
cnt++;
}
}
}
int ans = 0;
while (front != rear) {
int x = q[front].x, y = q[front++].y;
for (int i = 0; i < 4; i++) {
int new_x = x + dx[i], new_y = y + dy[i];
if (new_x >= 0 && new_x < m && new_y >= 0 && new_y < n &&-1==dis[new_x][new_y]&&grid[new_x][new_y]) {
dis[new_x][new_y] = dis[x][y] + 1;
q[rear].x = new_x;
q[rear++].y = new_y;
if (1 == grid[new_x][new_y]) {
cnt--;
ans = dis[new_x][new_y];
if (0 == cnt) {
break;
}
}
}
}
}
return cnt?-1:ans;
}
三、思路分析
- 模拟广度优先遍历的方法,将初始情况下所有腐烂的橘子看做一个超级源点来感染他们,初始时间为-1,则超级源点腐烂所有橘子的时刻为0。则-1时刻所有橘子都被视为新鲜的橘子。
- 用一个队列存储所有已腐烂的橘子,-1时刻存储0时刻要腐烂的橘子,0时刻存储1时刻被腐烂的橘子,依次往后递推。
- 边界设置:首先要保证在二维数组范围内,其次每次访问的元素必须未被访问过,也就是dis==-1则访问。最后单元格不能为空,grid!=0。上述条件,保证被访问的单元格,只能是新鲜的橘子。
- 由于广度优先遍历的特性,他是一圈一圈访问的,可以保证,一次遍历的结果,对应的dis就是每个点对应的腐烂时间,-1表示未被腐烂,或者空点。而ans最终一定等于最后一个被腐烂的橘子,花费的时间。
四、代码分析
五、AC
六、复杂度分析
- 时间复杂度:O(mn) ,m是行数,n是列数,O(mn)是遍历所有元素的时间开销。
- 空间复杂度:O(mn),使用了额外的队列,大小为O(mn),使用了额外的dis二维数组,表示腐烂的时间,大小也为O(mn)。