Leetcode记录:模拟过程

螺旋矩阵

给你一个正整数 n ,生成一个包含 1n^2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

模拟顺时针画矩阵的过程:

  1. 填充上行从左到右
  2. 填充右列从上到下
  3. 填充下行从右到左
  4. 填充左列从下到上
  5. 由外向内一圈一圈这么画下去。

可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,会有很多bug,因此求解本题依然是要坚持循环不变量原则:例如左闭右开,代码如下:

vector<vector<int>> generateMatrix(int n) {
    vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈
    int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1)
    int count = 1; // 用来给矩阵中每一个空格赋值
    int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    int i,j;
    while (loop --) {
        i = startx;
        j = starty;

        // 下面开始的四个for就是模拟转了一圈
        // 模拟填充上行从左到右(左闭右开)
        for (j; j < n - offset; j++) {
            res[i][j] = count++;
        }
        // 模拟填充右列从上到下(左闭右开)
        for (i; i < n - offset; i++) {
            res[i][j] = count++;
        }
        // 模拟填充下行从右到左(左闭右开)
        for (; j > starty; j--) {
            res[i][j] = count++;
        }
        // 模拟填充左列从下到上(左闭右开)
        for (; i > startx; i--) {
            res[i][j] = count++;
        }

        // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
        startx++;
        starty++;

        // offset 控制每一圈里每一条边遍历的长度
        offset += 1;
    }

    // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    if (n % 2) {
        res[mid][mid] = count;
    }
    return res;
}

也可以实时更新上下左右四个边界来判断:

vector<vector<int>> generateMatrix(int n) {
    vector<vector<int>>ret(n,vector<int>(n,1));
    int left = 0,right = n - 1,top = 0,bottom = n - 1;
    int num = 1;
    while(num <= n * n){
        for(int i = top,j = left;j <= right;j++){
            ret[i][j] = num++;
        }
        ++top;
        for(int i = top,j = right;i <= bottom;i++){
            ret[i][j] = num++;
        }
        --right;
        for(int i = bottom,j = right;j >= left;j--){
            ret[i][j] = num++;
        }
        --bottom;
        for(int i = bottom,j = left;i >= top;i--){
            ret[i][j] = num++;
        }
        ++left;
    }
    return ret;
}