April 21, 2020

Leetcode 54 - Spiral Matrix in Clojure

Due to the entrenched interview process across the tech industry, every now and then I find myself needing to brush off my data structure/algorithm cob web prior to braving through another round of job interviews. Regardless of how many years of experience one has and ones domain knowledge, I believe that being at least familiar with the type of technical questions that might be presented during an interview is absolutely crucial.

On the other hand, I hate grinding through leetcode problems. If I have to do it, I might as well do it in a language I love. Some people out there may raise some concerns around using a non-mainstream language during an interview. I can attest that I did most of mine in clojure. Not only no one raised any objections, most were quite intrigued.

Leetcode is actually a good avenue to showcase the power and beauty of Clojure. Here I'll go over my approach to the problem step by step.

The following is the problem statement for Spiral Matrix

Given a matrix of m x n elements (m rows, n columns),
return all elements of the matrix in spiral order.

We can easily solve this by extracting the first row, followed by rotating the remainder of the matrics counter-clockwise 90 degrees. Repeat, until we exhaust the entire matrix.

Let's assume that our input is a vector of vectors. For example,

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

Let's focus on the rotation alone first. The "difficult" part is to regroup the numbers vertically. We can easily map across all the nested vectors in lockstep and reorganize the numbers into a list or a vector.

(map vector
     [1 2 3]
     [4 5 6]
     [7 8 9])

Unfortunately, the input data is a vector of vectors. Only if we can unpack the top level vector, similar to Python's * operator. This is exactly what apply is for.

(apply map vector [[1 2 3]
                   [4 5 6]
                   [7 8 9]])

Now we just need them in the reverse order. This is trivial. Simply call reverse

(defn rotate [input]
  (reverse (apply map vector input))
  )

(rotate [[1 2 3]
         [4 5 6]
         [7 8 9]])

We'll use loop/recur to keep grabbing the first vector and rotate the rest until the input matrix withers away in front of our eyes.

(let [input [[1 2 3]
             [4 5 6]
             [7 8 9]]]
  (loop [[first-row & more-rows] input
         accum []]
    (if (nil? more-rows)
      (concat accum first-row)
      (recur (rotate more-rows) (concat accum first-row)))
    ))

Just turn that into a function and we are done.

(defn spiral-print [input]
  (loop [[first-row & more-rows] input
         accum []]
    (if (nil? more-rows)
      (concat accum first-row)
      (recur (rotate more-rows) (concat accum first-row)))
    ))
(spiral-print [[1 2 3]
               [4 5 6]
               [7 8 9]])

Usually one needs to come up with space and time complexity in terms of big O. I'll leave that to you. You can find the code on my github repo.

Tags: leetcode