剑指OFFER 顺时针打印矩阵
剑指OFFER 顺时针打印矩阵
试错记录
递归解(代码有错)
class Solution {
public:
vector<int> res;
void printSuround(vector<vector<int>> &m,int x,int y)
{
int size = m.size();
if(m[x][y]==-1)return;
while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
{
res.push_back(m[x][y]);
m[x][y]=-1;
y++;
}
y--;
x++;
while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
{
res.push_back(m[x][y]);
m[x][y]=-1;
x++;
}
x--;
y--;
while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
{
res.push_back(m[x][y]);
m[x][y]=-1;
y--;
}
y++;
x--;
while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
{
res.push_back(m[x][y]);
m[x][y]=-1;
x--;
}
x++;
y++;
printSuround(m,x,y);
}
vector<int> printMatrix(vector<vector<int>> matrix) {
res.clear();
if(matrix.size() == 0)return res;//如果矩阵空则返回一个空vector
printSuround(matrix,0,0);
return res;
}
};
循环解(代码有错)
不使用递归,转换为循环,仍超时... 懵了
class Solution {
public:
vector<int> res;
pair<int,int> fac[4] = {{0,1},{1,0},{0,-1},{-1,0}};
vector<int> printMatrix(vector<vector<int>> m) {
res.clear();
if(m.size() == 0)return res;//如果矩阵空则返回一个空vector
if(m.size() == 1)
{
res.push_back(m[0][0]);
return res;
}
int x = 0;
int y = 0;
int size = m.size();
while(m[x][y] != -1)
{
for(int i=0;i<4;i++)
{
while(x>=0 && y>=0 && x<size && y<size && m[x][y] != -1)
{
res.push_back(m[x][y]);
m[x][y] = -1;
x += fac[i].first;
y += fac[i].second;
}
x -= fac[i].first;
y -= fac[i].second;
x += fac[(i+1)%4].first;
y += fac[(i+1)%4].second;
}
}
return res;
}
};
现在还没弄明白是哪个步骤这么耗时,复杂度应该是差不多,先放这,以后弄明了再补充
找出原因
算法的思路实际并没有问题,而是因为考虑少了一些特殊情况
出现超时其实是因为 当只输入单行或者单列时候出现了死循环(数组越界访问)
解决办法:
-
在大while里面再次限制x,y的值,当旋转一周后,仍然没有矩阵元素可加入res数组中就直接结束,不再继续旋转(继续旋转可能会使得访问越界)
-
前面的代码是使用-1来标记元素是否被访问过(这种方式有缺陷,如果矩阵的元素本身有-1存在就会混淆判断),下面改用了哈希表,在避免混淆的同时避免重复访问vector数组,效率得到了很大提升,相同的代码在leetcode上提交,运行速度简直恐怖.
题目 54.Spiral Matrix Runtime: 0 ms, faster than 100.00% of C++ online submissions for Spiral Matrix. Memory Usage: 8.8 MB, less than 24.24% of C++ online submissions for Spiral Matrix.
下面给出正确代码:
class Solution {
public:
vector<int> res;
pair<int,int> fac[4] = {{0,1},{1,0},{0,-1},{-1,0}};//旋转因子
map<pair<int,int>,bool> hash;
vector<int> printMatrix(vector<vector<int>> m) {
res.clear();
if(m.size() == 0)return res;//如果矩阵空则返回一个空vector
int x = 0;
int y = 0;
int x_size = m.size();//行数
int y_size = m[0].size();//列数
//这里存在短路,前面条件不满足就不查哈希表了
while(x>=0 && y>=0 && x<x_size && y<y_size && !hash[pair<int,int>(x,y)])
{
for(int i=0;i<4;i++)//四个方向,旋转四次
{
//这里存在短路,前面条件不满足就不查哈希表了
while(x>=0 && y>=0 && x<x_size && y<y_size && !hash[pair<int,int>(x,y)])
{
res.push_back(m[x][y]);
hash[pair<int,int>(x,y)] = true;
x += fac[i].first;
y += fac[i].second;
}
x -= fac[i].first;
y -= fac[i].second;//越界返回
x += fac[(i+1)%4].first;
y += fac[(i+1)%4].second;//前往下一个元素
}
}
return res;
}
};
其他题解
下面代码不是我写的,学习一下别人是怎么写的
从代码上看效率,不管是空间复杂度还是时间复杂度都是比较好的.但是逻辑需要很清晰才能写出来
class Solution {
public:
vector<int> printMatrix(vector<vector<int>> matrix) {
int row=matrix.size();
int col=matrix[0].size();
vector<int> result;
if(row==0||col==0)
return result;
int left=0,right=col-1,top=0,btm=row-1;
while(left<=right&&top<=btm)
{
for(int i=left;i<=right;i++)
result.push_back(matrix[top][i]);
if(top<btm)
for(int i=top+1;i<=btm;i++)
result.push_back(matrix[i][right]);
if(top<btm&&left<right)
for(int i=right-1;i>=left;i--)
result.push_back(matrix[btm][i]);
if(top+1<btm&&left<right)
for(int i=btm-1;i>=top+1;i--)
result.push_back(matrix[i][left]);
left++;right--;top++;btm--;
}
return result;
}
};