Showing posts sorted by relevance for query spiral matrix print. Sort by date Show all posts
Showing posts sorted by relevance for query spiral matrix print. Sort by date Show all posts

Tuesday, July 16, 2019

54. Spiral Matrix - practice in 2015

Here is my sharing on Leetcode.com.

It is tough job to write a C# solution to go over spiral array to print out all elements in the matrix. I wrote C# solution but I failed multiple test cases, I learned that it is easy to make mistake to count same element twice. Compare to use extra space to mark visit, the solution is prone to the bug for duplicated output.
Also back in 2015, I also need to learn C# better to write more readable code.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _54_Spiral_matrix_2015_June
{
    class Program
    {
        static void Main(string[] args)
        {
        }

        /// <summary>
        /// code written in June 12, 2015
        /// </summary>
        /// <param name="matrix"></param>
        /// <returns></returns>
        public IList<int> SpiralOrder(int[,] matrix)
        {
            IList<int> list = new List<int>();

            int len1 = matrix.GetLength(0);
            int len2 = matrix.GetLength(1);

            int[][] matrix_input = new int[len1][];

            for (int i = 0; i < len1; i++)
                matrix_input[i] = new int[len2];

            for (int i = 0; i < len1; i++)
                for (int j = 0; j < len2; j++)
                {
                    matrix_input[i][j] = matrix[i, j];
                }

            ArrayList al = spiralOrder_2(matrix_input);

            foreach (object s in al)
            {
                list.Add((int)s);
            }
            return list;
        }

        public ArrayList spiralOrder_2(int[][] matrix)
        {
            if (matrix == null || matrix.Length == 0 || matrix[0].Length == 0)
                return new ArrayList();
            return spiralOrder_3(matrix, 0, 0, matrix.Length, matrix[0].Length);
        }

        /**
         * Latest update: June 12, 2015 
         * Leetcode: spiral array
         * http://gongxuns.blogspot.ca/2012/12/leetcode-spiral-matrix.html
         * Test case: 
         * 1. empty array 
         * 2. one element:           1 -
         * 2B. one row : 1 2 --
         * 3. one column : 1 |
         *                 2 |
         * 4. more than 1 row, 
         *    or more than 1 column   
         *     1 2
         *     3 4
         *     output: 1 2 4 3 
         * 5. 3 rows, 3 columns
         *    1 2 3
         *    4 5 6
         *    7 8 9
         *    output: 1 2 3 6 9 8 7 4 5 
         * 
         */
        public ArrayList spiralOrder_3(int[][] matrix, int x, int y, int m, int n)
        {
            ArrayList res = new ArrayList();
            // test case: empty array
            if (m <= 0 || n <= 0) return res;

            // test case 2: one row and one column
            if (m == 1 && n == 1)
            {
                res.Add(matrix[x][y]);
                return res;
            }

            //  row, from left to right 
            for (int i = 0; i < n - 1; i++)
            {
                res.Add(matrix[x][y++]);
            }

            //  column, from top to down
            for (int i = 0; i < m - 1; i++)
            {
                res.Add(matrix[x++][y]);
            }

            // conditional: second row, from right to left 
            if (m > 1)
            {
                for (int i = 0; i < n - 1; i++)
                {
                    res.Add(matrix[x][y--]);
                }
            }

            // conditional: second column, from bottom to top
            if (n > 1)
            {
                for (int i = 0; i < m - 1; i++)
                {
                    res.Add(matrix[x--][y]);
                }
            }

            // test case: one row, 1 2 3, where 1 2 is procesed above and 3 is left for next round 
            // one column:
            if (m == 1 || n == 1)
            {
                ArrayList l = spiralOrder_3(matrix, x, y, 1, 1);

                foreach (object val in l)
                    res.Add((int)val);
            }
            else
            {
                ArrayList l = spiralOrder_3(matrix, x + 1, y + 1, m - 2, n - 2);
                foreach (object val in l)
                    res.Add((int)val);
            }

            return res;
        }    
    }
}


Wednesday, March 16, 2016

Mock interview (4th practice): Matrix Spiral Print

March 16, 2016

Problem statement

Given a 2D array (matrix) named M, print all items of M in a spiral order, clockwise.
For example:

M  =  1    2    3    4   5
         6    7    8    9  10
       11  12  13  14  15
       16  17  18  19  20

The clockwise spiral print is:  1 2 3 4 5 10 15 20 19 18 17 16 11 6 7 8 9 14 13 12

Mock interview practice


I had a mock interview recently and my algorithm is Spiral matrix. The code I wrote in mock interview using C# is here.

Let us take a look at evaluation from the mock interviewer, as a matter of fact the peer gave me the honest feedback, I have to figure out how to work on the improvement:



Code review


After the mock interview, I thought about more how to improve the solution. I do not have good idea to solve the problem. Based on my mathematics background and I tried to define how many variables in the problem.


Let us look at one variable, let us call it layer, using variable name row, value is from 0 to (N+1) / 2, where N is how many columns in the matrix. So, the spiral matrix output is to follow the order of clockwise starting from (0,0). 

N - how many columns
M - how many rows

Four corners are left-top, right-top, bottom-right, bottom-left, abbreviation using four variables: LT, RT, BR, BL


   LT     coordinates:   ( row,             row )    
   RT    coordinates:   ( row,             N - 1 - row)  
   BR    coordinates:   ( M - 1 - row,  N -1 - row)
   BL     coordinates:   ( M - 1 - row,  row)


private static void leftToRight(Coordinate[] A)

TopToDown, RightToLeft, and DownToUp 
  
           row

            0     1       2
            -------------->
           1    2     3   4   5
            6    7     8   9  10
           11  12  13  14  15
           16  17  18  19  20

The above case, LT = (0, 0), RT = (0, 4), BR = (3, 4), BL = (3, 0)

C# practice code based on the above idea is here.  

Continue to improve the idea. 

LT, BR those two pointers should be checked on the conditions, M – 1 - row >= row, N – 1 - row >= row; in other words, left top pointer is above the bottom right pointer, therefore it should be row <= Math.Min((M - 1)/ 2, (N - 1)/ 2).


It is true that the idea I came out just after the mock interview was not so good. But the hard work spirit is good, and also it is very good to write down the idea and review later on.

Issues found in mock interview


I like to write down a few issues in my practice. 

1. Jagged array initialization
Julia spent more than 5 minutes to look up the internet. 

2. Try another idea. Use one variable instead of two variables. 
Assuming that N rows and M columns, how many layers of spiral? Use the variable i to denote the number. 

It should be from 0 to (N+1)/2, but it is hard to figure out correct answer first time, it should be 0 to 
Math.Min((M-1)/2, (N-1)/2). 

Julia spent more than 20 minutes to debug in the practice. 

Spiral matrix practice in 2015



I practice once in 2015 on Leetcode 54 Spiral matrix algorithm. I found the blog and it is very interesting to read the code I wrote back in 2015 June. Here is the blog about the practice. 


Follow up 


May 23, 2017

It is such great experience to compare the current practice to the one in 2016. Julia learned that she made such great improvement on coding readability, and she starts to know how important it is to document and track the progress. 

After considering a few of options, it is much easy to write a while loop to track the total visited nodes in the original array. 

Instead of using i, j, use variable row and col because it is more meaningful. 

Do not run the code and depend on the compiler; 

Test the code by yourself. 

C# practice is here. 

In order to make sure that the code is working, Julia used the same idea to write a solution for Leetcode 54. The solution failed to pass one row test case [1, 2, 3]. 

The C# code is fixed to add one row and one column checking. The code is here. 



Tuesday, July 4, 2023

StackExchange | Code Review | Leetcode 54: Spiral Matrix

Here is the link.
7

Problem statement

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. For example, Given the following matrix:
[
  [ 1, 2, 3 ],
  [ 4, 5, 6 ],
  [ 7, 8, 9 ]
]
You should return [1,2,3,6,9,8,7,4,5].

My introduction of algorithm

This is medium level algorithm on Leetcode.com. I have practiced over ten times from March 2017 to Jan. 2018. I wrote the algorithm in mock interview five times and also watched five peers to work on the algorithm. I experienced the pain to write a for loop inside a while loop four times, I wrote the code with a bug to print one row matrix twice, duplicate the output on last row and first column. And also I watched a few times the peer to struggle with so many bugs. Overall it is an algorithm with a lot of fun to play with.

How to write bug free solution in mock interview?

First time I had a mock interview on another mock interview platform on Jan. 23, 2018, and it is anonymous one.

The interviewer asked me if I can write the solution only using one loop instead of four for loops inside one while loop whereas two for loops to iterate on row, either top or bottom row; two for loops to iterate on last column or first column.

I had worked on the algorithm over 10 times on mock interview, but I never come out the completed idea based on limited time concern and buggy for loops. None of my peers came out the idea and wrote the similar ideas, and I only had discussion with one peer before. As an interviewer or interviewee, I did thought about four for loops are problematic as well.

One time I complained to the peer in mock interview when I worked on the four for loop of this spiral matrix problem. I told the peer that I like to use extra array to mark visit, so that my four for loop can always go from 0 to rows - 1 or 0 to cols - 1. The code will take extra time to iterate on visited elements but definitely no worry to define the start and end position. The peer's advice is not to be a hacker in mock interview, you should always follow the interviewer's hint or advice. That is only time I made very close to this new idea.

It is helpful to review all past practices through the code blogs. Here is one of blogs about the practice on spiral matrix algorithm.

Analysis of the algorithm

One thing I like to do is to write down some analysis of the algorithm before I write any code in mock interview. And it is also very helpful for me to go over various ideas to find the optimal one.

I also like to practice this approach when I ask a question on this site.

Here are some keywords for the spiral matrix algorithm.

Direction - There are four directions. Change direction if need, in the order of clockwise, starting from top left corner (0,0).
Range - Stay inside the array
Visit - visit each element in the array only once. Do not visit more than once.
Order - follow the order of clockwise, start from (0,0).

Quick solution with readable code

I wrote a C# solution and use extra space to declare an array to mark the element in the matrix is visited or not. To change direction, if the current row and column is out of boundary of matrix or it is visited before. I wrote the solution after the mock interview, I could not believe that I need so many hints in the mock interview after so many practice, one hint for four directions, one hint using extra array for visited array.

Here is C# solution.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MatrixSpiralPrint
{
    class Program
    {
        /// <summary>
        /// Leetcode Spiral Matrix
        /// https://leetcode.com/problems/spiral-matrix/description/
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            var spiral = MatrixSpiralPrint(new int[,] { { 1, 2, 3 }, { 8, 9, 4 }, { 7, 6, 5 } });
            Debug.Assert(String.Join(",", spiral).CompareTo("123456789") == 0);
        }

        /// <summary>
        /// Navigate the direction automatically by checking boudary and checking 
        /// the status of element visited status. 
        /// Only one loop, perfect idea to fit in mock interview or interview 
        /// 20 minutes setting         
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        public static int[] MatrixSpiralPrint(int[,] array)
        {
            if (array == null || array.GetLength(0) == 0 || array.GetLength(1) == 0)
            {


Why use integer for on/off status?

The values in visited are either 0 or 1. A boolean matrix would be a natural choice for the purpose.

Do you really need the extra storage?

Using the visited array makes the implementation somewhat simpler. Another way, without extra storage would be keeping track of the number of steps to do in the current direction. Think about the correct values and observe the pattern:

  • Top: columns
  • Right: rows - 1
  • Bottom: columns - 1
  • Left: rows - 2
  • Top: columns - 2
  • Right: rows - 3
  • Bottom: columns - 3
  • Left: rows - 4
  • ...

Basically, alternating the column and row counts, decreasing by 1 on every direction change. When the next number of steps is 0, it's time to stop. A bit more tricky to write, but using constant extra storage.

Handling special cases

The case of 0 rows or 0 columns doesn't need special treatment. The result array will be created empty, and the main loop will not do any steps.

The case of null value for the array is non-sense input. If that ever happens, it looks suspiciously as a malfunction in the caller. It would be better to signal that there is a problem by throwing an explicit exception.

Naming

fourDirections contains 4 directions. Don't name a collection by its size. Just directions would be better.

  • Extra storage is not necessary. I agree with your advise on this.  Jan 30, 2018 at 21:15   
  • I got complaint about memorizing the solution in mock interview. Since I choose to work on same 30 algorithms again and again on mock interview, I know all the common solutions and mistakes. But exploring new ideas are challenging still in the mock interview, I try to write simple code. Four variables to replace visited array are easy to make mistakes in interview, I think.  Jan 30, 2018 at 21:34   
  • 2
    @JianminChen the purpose of programming interviews should not be to find perfect solutions, but to see your thought process, ability to split larger problems to smaller ones, and building up something that works through iteration. So rather than perfecting the solution to a small set of specific problems, I recommend to solve a wide range of problems. 
    – janos
     Jan 30, 2018 at 21:44
  • I agree with you on this. It is not good to be opportunistic. But one popular saying is to write production ready code in interview, I also ask myself which one is more production ready code? More space less buggy or optimal space with more buggy variables?  Jan 30, 2018 at 22:40   
  • I had a mock interview as an interviewer on Jan. 30, 2018, so I asked the peer to solve the algorithm; he gave exactly the same idea you advise, using direction array and also use four variables instead of visited array, he wrote 10 minutes but code has a few issues like grammar errors. Here is C# code I completed based on his code after the mock interview: gist.github.com/jianminchen/fca45bb38410b59f580f88a0051ae2a8  Feb 2, 2018 at 6:24   
  • I continuously studied and then I found exactly same idea advised by janos. Here is the leetcode discussion link: discuss.leetcode.com/topic/15558/…  Feb 10, 2018 at 23:40   
  • I wrote the implementation of the idea advised by janos. I did not really understand quickly about the idea by reading the above code review until I wrote the C# code based on Leetcode discussion, and then I found that the idea is exactly the same. Here is the C# code integerated all the above code review advices and avoid using extra array visited. gist.github.com/jianminchen/1adcda667cc22247df154a40fcc57d2c  Feb 10, 2018 at 23:43   
  • I wrote C# solution with optimal space O(1), using direction array to adjust direction automatically. Here is the link: leetcode.com/problems/spiral-matrix/discuss/407992/…  Dec 7, 2019 at 1:47