六月集训(第11天)—矩阵
矩阵
1. 面试题 01.08. 零矩阵
思路:
标记0所在得行和列,对应行列全部置为0。
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int n = matrix.size(), i;
int m = matrix[0].size(), j;
bool row[n], colomn[m];
memset(row, false, sizeof(row));
memset(colomn, false, sizeof(colomn));
for (i = 0; i < n; ++i) {
for (j = 0; j < m; ++j) {
if (!matrix[i][j]) {
if (!row[i]) row[i] = true;
if (!colomn[j]) colomn[j] = true;
}
}
}
for (i = 0; i < n; ++i) {
if (row[i]) {
for (j = 0; j < m; ++j) matrix[i][j] = 0;
}
}
for (j = 0; j < m; ++j) {
if (colomn[j]) {
for (i = 0; i < n; ++i) matrix[i][j] = 0;
}
}
}
};
2. 73. 矩阵置零
思路:
思路同第一题,优化掉$O(n)$的存储空间。
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int n = matrix.size(), i;
int m = matrix[0].size(), j;
bool colomn[m], row_flag = false;
memset(colomn, false, sizeof(colomn));
for (i = 0; i < n; ++i) {
row_flag = false;
for (j = 0; j < m; ++j) {
if (matrix[i][j] == 0) {
row_flag = true;
if (!colomn[j]) {
for (int k = 0; k <= i; ++k) matrix[k][j] = 0;
colomn[j] = true;
}
}
if (j == m - 1 && row_flag) {
for (int k = 0; k < m; ++k) matrix[i][k] = 0;
} else if (j == m - 1){
for (int k = 0; k < m; ++k) {
if (colomn[k]) matrix[i][k] = 0;
}
}
}
}
}
};
3. 1727. 重新排列后的最大子矩阵
思路:
统计每一行作为底边,向上生长可达得最大高度(即红色部分)。
偷英雄哥的图解释一下:

对每行的最大可达高度升序排列,即当前行作为底边对应的最大面积就是当前列的最大高度 * (colomn - j),遍历一行得到该行的最大面积。对每一行更新答案,得到最终答案。
class Solution {
public:
int largestSubmatrix(vector<vector<int>>& matrix) {
int n = matrix.size(), i;
int m = matrix[0].size(), j;
int pline[m], tpline[m];
int ans = 0;
memset(pline, 0, sizeof(pline));
for (i = 0; i < n; ++i) {
for (j = 0; j < m; ++j) {
if (matrix[i][j] == 0) {
pline[j] = 0;
} else {
pline[j] += 1;
}
}
for (j = 0; j < m; ++j) tpline[j] = pline[j];
sort(tpline, tpline + m);
for (j = 0; j < m; ++j) {
ans = max(ans, tpline[j] * (m - j));
}
}
return ans;
}
};
4. 1034. 边界着色
思路:
题意 利用给定颜色给grid[row][col]所在的连通域的边界置为color。
E.g.1 grid = [[1,1],[1,2]], row = 0, col = 0, color = 3
[1,1]-->[3,3]
[1,2]-->[3,2]
E.g.2 grid = [[1,2,2],[2,3,2]], row = 0, col = 1, color = 3
[1,2,2]-->[1,3,3]
[2,3,2]-->[2,3,3]
E.g.3 grid = [[1,1,1],[1,1,1],[1,1,1]], row = 1, col = 1, color = 2
[1,1,1]-->[2,2,2]
[1,1,1]-->[2,1,2]
[1,1,1]-->[2,2,2]
利用bfs从grid[row][col],开始搜索,找到其联通域的边界记录在margin中,最后利用margin将grid中目标联通域的边界着色,返回grid。
struct POS {
int x, y;
};
class Solution {
int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
void bfs(vector<vector<int>> &grid, int row, int col, int color, vector<POS> &margin) {
int gird_n = grid.size(), i;
int grid_m = grid[0].size(), j;
bool vis[gird_n][grid_m];
int precolor = grid[row][col];
memset(vis, false, sizeof(vis));
queue<POS> Q;
Q.push({row, col});
vis[row][col] = true;
while (!Q.empty()) {
POS start = Q.front();
Q.pop();
vis[start.x][start.y] = true;
POS temp_d;
for (int k = 0; k < 4; ++k) {
temp_d.x = start.x + dir[k][0];
temp_d.y = start.y + dir[k][1];
// 记录边界坐标
if (temp_d.x < 0 || temp_d.x >= gird_n || temp_d.y < 0 || temp_d.y >= grid_m) { /* 在网格边界为边界 */
margin.push_back(start);
continue;
}
if (vis[temp_d.x][temp_d.y]) continue;
if (grid[temp_d.x][temp_d.y] != precolor) { /* 在连通域边界 */
margin.push_back(start);
continue;
}
Q.push(temp_d);
}
}
}
public:
vector<vector<int>> colorBorder(vector<vector<int>>& grid, int row, int col, int color) {
vector<POS> margin;
bfs(grid, row, col, color, margin);
int margin_size = margin.size(), i;
for (i = 0; i < margin_size; ++i) {
grid[margin[i].x][margin[i].y] = color;
}
return grid;
}
};
东方欲晓,莫道君行早。

浙公网安备 33010602011771号