该题的直接思路就是将矩阵遍历,然后对每一个元素进行行和列置零,不过这样的时间复杂度过高,可以考虑在此基础上进行优化。用一个行和列的标记数组来记录该行或列是否全被置零,
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m=matrix.size();
int n=matrix[0].size();
vector<int>row(m),col(n);
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(!matrix[i][j]){
row[i]=col[j]=true;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(row[i]||col[j]){
matrix[i][j]=0;
}
}
}
}
};
可以记录当前移动的步数来进行计算,用标记数组判断该位置是否已经走过。外循环条件为走过的总步数与格子数目的关系,内循环则是按照四个方向已经下一个位置的合理性来判断是否可以进行该方向上的移动。
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<vector<int>> vis(m, vector<int>(n));
vector<int> ans;
int cnt = 1;
int x=0,y=0;
ans.push_back(matrix[x][y]);
vis[x][y] = 1;
while (cnt < m * n) {
while (y + 1 < n && !vis[x][y+1]) {
y++;
vis[x][y] = 1;
ans.push_back(matrix[x][y]);
cnt++;
}
while (x + 1 < m && !vis[x+1][y]) {
x++;
vis[x][y] = 1;
ans.push_back(matrix[x][y]);
cnt++;
}
while (y - 1 >= 0 && !vis[x][y-1]) {
y--;
vis[x][y] = 1;
ans.push_back(matrix[x][y]);
cnt++;
}
while (x - 1 >= 0 && !vis[x-1][y]) {
x--;
vis[x][y] = true;
ans.push_back(matrix[x][y]);
cnt++;
}
}
return ans;
}
};
题目要求将矩阵顺时针旋转90度,我们用一个辅助数组临时存储矩阵旋转后的位置,比如原来的元素在第i行第j列,顺时针旋转后就变成了第j行第n-i-1列。
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n=matrix.size();
vector<vector<int>>temp(n,vector<int>(n));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
temp[j][n-i-1]=matrix[i][j];
}
}
matrix=temp;
}
};
由题可知,每一行从左往右是升序的,从上往下是升序的,那么容易想到的两种想法是一是暴力枚举每一个数,而是对每一行进行二分。我们直接以右上角为起点,根据行列有序的性质,进行排除法,如果当前数字大于target,就向左移动,如果小于就向下移动,直到找到target。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m=matrix.size();
int n=matrix[0].size();
int row=0,col=n-1;
while(row<m&&col>=0){
if(matrix[row][col]==target){
return true;
}else if(matrix[row][col]>target){
col--;
}else{
row++;
}
}
return false;
}
};