SpiralMatrixII [source code]

public class SpiralMatrixII {
static
/******************************************************************************/
class Solution {
    public int[][] generateMatrix(int n) {
        int[][] matrix = new int[n][n];
        if (n == 0)
            return matrix;
        int[] dimensions = {n, n - 1};
        int x = 0, y = -1;
        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int dimens_idx = 0, val = 0, direction_idx = 0;
        while (dimensions[dimens_idx] > 0) {
            for (int i = 0; i < dimensions[dimens_idx]; i++) {
                int[] direction = directions[direction_idx];
                x += direction[0];
                y += direction[1];
                matrix[x][y] = ++val;
            }
            dimensions[dimens_idx]--;
            dimens_idx = (dimens_idx + 1) % 2;
            direction_idx = (direction_idx + 1) % 4;
        }
        return matrix;
    }
}
/******************************************************************************/

    public static void main(String[] args) {
        SpiralMatrixII.Solution tester = new SpiralMatrixII.Solution();
        int[][][] inputs = {
            {{3}}, {
             { 1, 2, 3 },
             { 8, 9, 4 },
             { 7, 6, 5 }
            },
        };
        for (int i = 0; i < inputs.length / 2; i++) {
            int n = inputs[2 * i][0][0];
            String ans_str = Matrix.printMatrix (inputs[2 * i + 1]);
            System.out.println (Printer.separator ());
            String output_str = Matrix.printMatrix (tester.generateMatrix (n));
            System.out.printf ("%d -> \n%s, expected: \n%s", 
                n, Printer.wrap (output_str, output_str.equals (ans_str) ? 92 : 91), ans_str
            );
        }
    }
}

这次决定用swap row and col那个思路来做一下; 那个思路其实就是一个手动做法, 自己知道手动怎么话spiral, 而不依赖撞墙的时候的自动转向;

还算顺利的写出来了, 速度是2ms (51%); 注意一个dummy start的技巧就行了: 因为你第一行走完, 你在(0, 2)的位置, 你实际上是下一个iteration: (1,2)..(2.2)的dummy start, 所以最开始第一个iteration之前最好有一个dummy start; 然后dimension和direction的state都要设置到对应第一个iteration的状态, 这样进去就可以直接执行; 另外, val的初始值也要注意, 这里因为最后要求print的是1based的, 所以这里的val的dummy start应该是0而不是-1;


没有editorial;


@StefanPochmann said in 4-9 lines Python solutions:

Solution 1: Build it inside-out - 44 ms, 5 lines

Start with the empty matrix, add the numbers in reverse order until we added the number 1. Always rotate the matrix clockwise and add a top row:

    ||  =>  |9|  =>  |8|      |6 7|      |4 5|      |1 2 3|  
                     |9|  =>  |9 8|  =>  |9 6|  =>  |8 9 4|  
                                         |8 7|      |7 6 5|  

The code:

def generateMatrix(self, n):  
    A, lo = [], n*n+1  
    while lo > 1:  
        lo, hi = lo - len(A), lo  
        A = [range(lo, hi)] + zip(*A[::-1])  
    return A  

While this isn't O(n^2), it's actually quite fast, presumably due to me not doing much in Python but relying on zip and range and + being fast. I got it accepted in 44 ms, matching the fastest time for recent Python submissions (according to the submission detail page).


Solution 2: Ugly inside-out - 48 ms, 4 lines

Same as solution 1, but without helper variables. Saves a line, but makes it ugly. Also, because I access A[0][0], I had to handle the n=0 case differently.

def generateMatrix(self, n):  
    A = [[n*n]]  
    while A[0][0] > 1:  
        A = [range(A[0][0] - len(A), A[0][0])] + zip(*A[::-1])  
    return A * (n>0)  

Solution 3: Walk the spiral - 52 ms, 9 lines

Initialize the matrix with zeros, then walk the spiral path and write the numbers 1 to n*n. Make a right turn when the cell ahead is already non-zero.

def generateMatrix(self, n):  
    A = [[0] * n for _ in range(n)]  
    i, j, di, dj = 0, 0, 0, 1  
    for k in xrange(n*n):  
        A[i][j] = k + 1  
        if A[(i+di)%n][(j+dj)%n]:  
            di, dj = dj, -di  
        i += di  
        j += dj  
    return A  

可以大概看看, 主要好像还是耍的Python的各种语法;


@qwl5004 said in My Super Simple Solution. Can be used for both Spiral Matrix I and II:

This is my solution for Spiral Matrix I, [https://oj.leetcode.com/discuss/12228/super-simple-and-easy-to-understand-solution][1]. If you can understand that, this one is a no brainer :)

Guess what? I just made several lines of change (with comment "//change") from that and I have the following AC code:

public class Solution {  
    public int[][] generateMatrix(int n) {  
        // Declaration  
        int[][] matrix = new int[n][n];  

        // Edge Case  
        if (n == 0) {  
            return matrix;  
        }  

        // Normal Case  
        int rowStart = 0;  
        int rowEnd = n-1;  
        int colStart = 0;  
        int colEnd = n-1;  
        int num = 1; //change  

        while (rowStart <= rowEnd && colStart <= colEnd) {  
            for (int i = colStart; i <= colEnd; i ++) {  
                matrix[rowStart][i] = num ++; //change  
            }  
            rowStart ++;  

            for (int i = rowStart; i <= rowEnd; i ++) {  
                matrix[i][colEnd] = num ++; //change  
            }  
            colEnd --;  

            for (int i = colEnd; i >= colStart; i --) {  
                if (rowStart <= rowEnd)  
                    matrix[rowEnd][i] = num ++; //change  
            }  
            rowEnd --;  

            for (int i = rowEnd; i >= rowStart; i --) {  
                if (colStart <= colEnd)  
                    matrix[i][colStart] = num ++; //change  
            }  
            colStart ++;  
        }  

        return matrix;  
    }  
}

Obviously, you could merge colStart and colEnd into rowStart and rowEnd because it is a square matrix. But this is easily extensible to matrices that are m*n.

Hope this helps :)

[1]: https://oj.leetcode.com/discuss/12228/super-simple-and-easy-to-understand-solution

@lovesly said in My Super Simple Solution. Can be used for both Spiral Matrix I and II:

    public int[][] generateMatrix(int n) {  
        int[][] res = new int[n][n];  

        int cur = 1;  
        int rowBegin = 0;  
        int rowEnd = n - 1;  
        int colBegin = 0;  
        int colEnd = n - 1;  

        while(cur <= n * n) {  
                int i = rowBegin;  
                int j = colBegin;  
                //left to right  
                for(j = colBegin ; j <= colEnd; j++){  
                    res[rowBegin][j] = cur++;  
                }  
                rowBegin++;  
                //top to bot  
                for(i = rowBegin ; i <= rowEnd; i++){  
                    res[i][colEnd] = cur++;  
                }  
                colEnd--;  
                //right to left  
                for(j = colEnd ; j >= colBegin; j--){  
                    res[rowEnd][j] = cur++;  
                }  
                rowEnd--;  
                //bot to top  
                for(i = rowEnd; i >= rowBegin; i--){  
                    res[i][colBegin] = cur++;  
                }  
                colBegin++;  
        }  
        return res;  
    }

Actually you don't need "if condition", because it's n*n matrix.

这个就是上一题见过一次的用result size来terminate的技巧;


discussion基本还是第一题见到过的解法, 所以其实这两题是差不多的; 我上面这个代码已经是submission最优;


Problem Description

Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.

For example,
Given n = 3,

You should return the following matrix:

[  
 [ 1, 2, 3 ],  
 [ 8, 9, 4 ],  
 [ 7, 6, 5 ]  
]

Difficulty:Medium
Total Accepted:95.8K
Total Submissions:235.3K
Contributor:LeetCode
Related Topics
array
Similar Questions
Spiral Matrix

results matching ""

    No results matching ""