[面试金典]顺时针打印矩阵

题目链接:http://www.nowcoder.com/practice/9b4c81a02cd34f76be2659fa0d54342a?rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

问题

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵:

1234
5678
9101112
13141516

则依次打印出数字:
1→2→3→4→8→12→16→15→14→13→9→5→6→7→11→10.

分析

一开始把他当做迷宫问题处理,假如碰到边界或者访问过的点,就按照→, ↓, ←, ↑的顺序依次变向,直到周围的四个方向的点都是访问过的为止。

  • 边界的判断:0~size
  • 访问过的点:用一个矩阵来记录
  • 四个方向:{→, ↓, ←, ↑} = {{0,1}, {1,0}, {0, -1}, {-1, 0}}

然而杯具的是OJ结果是栈溢出,说白点就是我用的空间太大了。纠结蛋疼之际只能改变一下判断方法,剩下记录访问点的矩阵空间。方法就是记录访问边界

  • 初始化:横纵坐标的访问方位是{横坐标, 纵坐标} = {{0, size},{0, size}}
  • 访问了第一行后:纵坐标范围缩小为{横坐标, 纵坐标} = {{0, size},{1, size}}
  • 访问了最后一列后:横坐标范围缩小为{横坐标, 纵坐标} = {{0, size - 1},{1, size}}
  • 依次循环记录…

这样用一个2*2的数据就可以代替一个矩阵了,太棒了!

小结

又学会了一项优化技能;其次是二维vector的初始化方法:

vector <vector<int> > hey(m, vector <int>(n, 0)); 

实现

方案一

class Solution {
public:
    bool check(vector <vector <bool> > m, int x, int y, int dx, int dy){
        int lx = m[0].size() - 1;
        int ly = m.size() - 1;
        if(x + dx < 0 || x + dx > lx || y + dy < 0 || y + dy > ly){
            return false;
        }
        if(m[x + dx][y + dy]){
            return false;
        }
        return true;
    }

    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector <int> rv;
        if(matrix.empty())
            return rv;
        int m = matrix.size();
        int n = matrix[0].size();
        vector <vector <bool> > fv(m, vector<bool>(n, false));
        int dy[4] = {1, 0, -1, 0};
        int dx[4] = {0, 1, 0, -1};
        bool flag = true;
        int i = 0, j = 0;
        rv.push_back(matrix[0][0]);
        fv[0][0] = true;
        //int T = m * n - 1;
        while(flag){
            flag = false;
            for(int k = 0; k < 4; k++){
                while(check(fv, i, j, dx[k], dy[k])){
                    flag = true;
                    i += dx[k];
                    j += dy[k];
                    rv.push_back(matrix[i][j]);
                    fv[i][j] = true;
                }
            }
        }
        return rv;
    }
};

方案二

class Solution {
public:
    bool check(int m[2][2], int x, int y, int dx, int dy){
        if(x + dx < m[0][0] || x + dx > m[0][1] || y + dy < m[1][0] || y + dy > m[1][1]){
            return false;
        }
        return true;
    }

    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector <int> rv;
        if(matrix.size() == 0 || matrix[0].size() == 0)
            return rv;
        int max[2][2] = {{0, 0}, {0, 0}};
        max[0][1] = matrix.size() - 1;
        max[1][1] = matrix[0].size() - 1;
        int dx[4] = {0, 1, 0, -1};
        int dy[4] = {1, 0, -1, 0};
        bool flag = true;
        int i = 0, j = 0;
        rv.push_back(matrix[0][0]);
        while(flag){
            flag = false;
            for(int k = 0; k < 4; k++){
                while(check(max, i, j, dx[k], dy[k])){
                    flag = true;
                    i += dx[k];
                    j += dy[k];
                    rv.push_back(matrix[i][j]);
                }
                switch (k) {
                    case 0:
                        max[0][0] += 1;
                        break;
                    case 1:
                        max[1][1] -= 1;
                        break;
                    case 2:
                        max[0][1] -= 1;
                        break;
                    case 3:
                        max[1][0] += 1;
                        break;
                    default:
                        break;
                }
            }
        }
        return rv;
    }
};

反思

迷宫问题是一个常见的问题,其思想还是很不错的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值