Spiral Matrix Traversal, Explained Step by Step (with a visualizer you can scrub)
We need to reformat the article into clean markdown with paragraphs, headings, lists, code blocks, preserving facts exactly. The article is long and contains repeated sections (the article appears duplicated). We must not add or remove information; we must preserve every fact, name, number, quotation exactly as given. However we can restructure and lightly polish wording for flow and grammar. Must not add introduction, conclusion, opinion, commentary. Must not repeat article title as heading. Must output only reformatted article body as markdown.
We need to break into short paragraphs, add section headings where topic shifts. Use bullet or numbered lists for enumerations. Use inline code or fenced code blocks for code, commands, identifiers.
We must preserve exact text for code snippets etc. Ensure we don't alter code. Also preserve numbers, names, etc.
We have duplicate content: The article appears twice (the same content repeated). We must preserve all facts; if we remove duplication we would be removing information (duplicate facts). The instruction: "Preserve every fact, name, number, and quotation exactly as given. Never invent, add, remove, or reorder information." That suggests we must keep the duplicated content as is, not remove duplicates. However we can reformat but cannot delete any information. So we must keep the duplicated sections. However we could combine them? That would be removing duplicate information (reordering? Actually removing duplicate would be removing information, which is not allowed). So we must keep both occurrences. That will lead to repetitive markdown but that's okay.
Thus we need to output the article exactly as given, but restructured into paragraphs and headings, while preserving all text. We must not add or remove any characters except for formatting (line breaks, markdown syntax). We must ensure we don't inadvertently change wording. We can adjust whitespace and add markdown syntax, but must keep the original words in same order? The instruction: "Only restructure and lightly polish wording for flow and grammar; do not add an introduction, conclusion, opinion, or commentary of your own." So we can slightly adjust wording for flow and grammar, but must preserve facts. Changing wording could be considered altering information? It says lightly polish wording for flow and grammar, so we can make minor edits but must keep meaning. However safer is to keep the exact sentences, just break them into paragraphs and add headings. We can also fix obvious typos? The article has some formatting issues like missing spaces, etc. We could lightly polish but must preserve facts. Probably okay to adjust minor punctuation and spacing.
We need to produce markdown. Let's outline sections:
- Introduction / description of spiral traversal and visualizer.
- What spiral traversal is (explanation with example).
- The idea: four bounds that close in.
- Here are the bounds on the 3 × 4 grid, ring by ring (maybe a table).
- The code (Python, JavaScript, C++).
- Notice the order of operations...
- The two if checks are not optional...
- Edge cases to test.
- Complexity.
- Variants you will meet.
- Try it with your own grid (description of visualizer features).
- Which one should I visualize next...
- Then repeated duplicate content (starting again from "Spiral traversal is the grid question...").
We need to preserve the duplicated content exactly as appears after the first block. The duplicated block includes the same paragraphs again, plus maybe some variations (like the table formatting). We'll need to include it again.
We must be careful not to inadvertently omit any text. Let's copy the article as given and then insert markdown formatting.
Given the length, we need to produce a manageable answer but must include all content. Let's extract the article text from the user message.
The article starts after "Article:" line. It includes:
"Spiral traversal is the grid question that looks easy on the whiteboard and then quietly breaks on a 1 × 4 matrix. I kept getting it wrong while learning, so I built a visualizer where you can step through it one cell at a time and watch the four bounds close in. This post is the explanation I wish I had, plus the exact code the visualizer runs. Try it out: Spiral Traversal visualizer (free, no sign-up, works on a phone). What spiral traversal is Take a 2D array and read it the way you would peel an onion: along the top row, down the right column, back along the bottom row, up the left column, then the same again on the smaller rectangle inside, until nothing is left. On this 3 × 4 grid: 1234 5678 9 10 11 12 the spiral order is 1 2 3 4 8 12 11 10 9 5 6 7 Ring one is the outer boundary (1 → 4 → 12 → 9 → 5). Ring two is what remains in the middle: 6 and 7. Every cell is visited exactly once, so the whole thing costs one step per cell, rows × cols . The idea: four bounds that close in Don't think in rings. Think in four numbers that describe the rectangle still to be visited: top and bottom : the first and last row that still have unvisited cells left and right : the first and last such column Walk one edge, then move that edge's bound inwards by one. Top row done? top += 1 . Right column done? right -= 1 . And so on. When top passes bottom or left passes right , the rectangle is empty and you stop. Here are the bounds on the 3 × 4 grid, ring by ring: After walking Visited top bottom left right (start) 0 2 0 3 top row 1 2 3 4 1 2 0 3 right column 8 12 1 2 0 2 bottom row (backwards) 11 10 9 1 1 0 2 left column (upwards) 5 1 1 1 2 top row again 6 7 2 1 1 2 After that last step top (2) is greater than bottom (1), so the loop ends. Twelve cells, twelve visits. The code The visualizer runs exactly this. visit is whatever you want to do with a cell: print it, push it to a list, add it to a sum. Python top , bottom , left , right = 0 , rows - 1 , 0 , cols - 1 while top <= bottom and left <= right : for j in range ( left , right + 1 ): visit ( a [ top ][ j ]) top += 1 for i in range ( top , bottom + 1 ): visit ( a [ i ][ right ]) right -= 1 if top <= bottom : for j in range ( right , left - 1 , - 1 ): visit ( a [ bottom ][ j ]) bottom -= 1 if left <= right : for i in range ( bottom , top - 1 , - 1 ): visit ( a [ i ][ left ]) left += 1 JavaScript function spiral ( a , visit ) { const rows = a . length , cols = a [ 0 ]. length ; let top = 0 , bottom = rows - 1 , left = 0 , right = cols - 1 ; while ( top <= bottom && left <= right ) { for ( let j = left ; j <= right ; j ++ ) visit ( a [ top ][ j ]); top ++ ; for ( let i = top ; i <= bottom ; i ++ ) visit ( a [ i ][ right ]); right -- ; if ( top <= bottom ) { for ( let j = right ; j >= left ; j -- ) visit ( a [ bottom ][ j ]); bottom -- ; } if ( left <= right ) { for ( let i = bottom ; i >= top ; i -- ) visit ( a [ i ][ left ]); left ++ ; } } } C++ int top = 0 , bottom = rows - 1 , left = 0 , right = cols - 1 ; while ( top <= bottom && left <= right ) { for ( int j = left ; j <= right ; j ++ ) visit ( a [ top ][ j ]); top ++ ; for ( int i = top ; i <= bottom ; i ++ ) visit ( a [ i ][ right ]); right -- ; if ( top <= bottom ) { for ( int j = right ; j >= left ; j -- ) visit ( a [ bottom ][ j ]); bottom -- ; } if ( left <= right ) { for ( int i = bottom ; i >= top ; i -- ) visit ( a [ i ][ left ]); left ++ ; } } Notice the order of operations on each edge: walk the edge first, then move the bound. Moving top before walking the top row skips a whole row. The two if checks are not optional This is the part that breaks. Remove the two guards and run it on a single row: 1 2 3 4 Without the guards, you get 1 2 3 4 3 2 1 . After the top row, top becomes 1 and is already past bottom (0). The right-column loop runs zero times, fine. But the bottom-row loop happily walks row bottom , which is the row you just printed, backwards. The guard if top <= bottom is what says "there is no separate bottom row left, skip it". The same thing happens with a single column and the left-column walk, which is what if left <= right prevents. It also bites on ordinary grids on the last ring. On the 3 × 4 example, without the guards the output ends … 5 6 7 6 : the final single-row ring gets its 7 → 6 walked back. A square grid hides the bug, which is exactly why people ship it: on a 3 × 3 the unguarded version happens to print 1 2 3 6 9 8 7 4 5 , which is correct. Set the rows slider to 1 in the visualizer and step through it. You will see the guard skip the bottom edge. Edge cases to test 1 × n and n × 1: the guards handle them. A 1 × 4 gives 1 2 3 4 , a 4 × 1 also gives 1 2 3 4 . 1 × 1: one visit, then top passes bottom . Empty grid: check rows == 0 before reading a[0].length . Non-square grids: always test on 3 × 4 and 4 × 3. Square grids hide off-by-one bugs. Complexity Time O(rows × cols) : every cell is visited once, and the bookkeeping is a constant amount per ring. Extra memory O(1) if you print or stream; O(rows × cols) if you collect the output into a list, which is the output itself, not overhead. You do not need a visited boolean matrix. It works, but it costs a second grid of memory and one more thing to get wrong. Variants you will meet LeetCode 54, Spiral Matrix: this exact function, returning the list. LeetCode 59, Spiral Matrix II: the reverse, fill an empty n × n grid with 1 … n² in spiral order. Same loop, write instead of read. Anticlockwise: walk the left column down first, then the bottom row, then the right column up, then the top row back. Spiral from the centre: run the clockwise spiral, collect the cells, reverse the list. Boundary only: the first ring is a full traversal in its own right. If you can write the boundary correctly, the spiral is a loop around it. There is a boundary traversal page too. Try it with your own grid Two things I built specifically for learning this: Every step of the visualizer is linkable. Scrub to the moment top passes bottom and press Copy link to this step ; the URL reopens exactly that state. Teachers: send one link to a class. Paste any matrix into the 2D Array Visualizer (JSON, a Python list, or plain rows of numbers), then click Traverse this grid → Spiral . Your grid travels with you, and you can switch to row-major, snake, or diagonal order without losing it. Everything is open source (MIT): github.com/salsadsid/visualizer . Each traversal is a small function that records steps; the visualizer plays them back. If a traversal or a grid algorithm is missing that you would like to see, say so in the comments or open an issue. Which one should I visualize next: flood fill, number of islands, or BFS in a maze? Spiral traversal is the grid question that looks easy on the whiteboard and then quietly breaks on a 1 × 4 matrix. I kept getting it wrong while learning, so I built a visualizer where you can step through it one cell at a time and watch the four bounds close in. This post is the explanation I wish I had, plus the exact code the visualizer runs. Try it out: Spiral Traversal visualizer (free, no sign-up, works on a phone). What spiral traversal is Take a 2D array and read it the way you would peel an onion: along the top row, down the right column, back along the bottom row, up the left column, then the same again on the smaller rectangle inside, until nothing is left. On this 3 × 4 grid: 1 2 3 4 5 6 7 8 9 10 11 12 the spiral order is 1 2 3 4 8 12 11 10 9 5 6 7 Ring one is the outer boundary (1 → 4 → 12 → 9 → 5). Ring two is what remains in the middle: 6 and 7. Every cell is visited exactly once, so the whole thing costs one step per cell, rows × cols . The idea: four bounds that close in Don't think in rings. Think in four numbers that describe the rectangle still to be visited: - top andbottom : the first and last row that still have unvisited cells - left andright : the first and last such column Walk one edge, then move that edge's bound inwards by one. Top row done? top += 1 . Right column done? right -= 1 . And so on. When top passes bottom or left passes right , the rectangle is empty and you stop. Here are the bounds on the 3 × 4 grid, ring by ring: | After walking | Visited | top | bottom | left | right | |---|---|---|---|---|---| | (start) | 0 | 2 | 0 | 3 | | | top row | 1 2 3 4 | 1 | 2 | 0 | 3 | | right column | 8 12 | 1 | 2 | 0 | 2 | | bottom row (backwards) | 11 10 9 | 1 | 1 | 0 | 2 | | left column (upwards) | 5 | 1 | 1 | 1 | 2 | | top row again | 6 7 | 2 | 1 | 1 | 2 | After that last step top (2) is greater than bottom (1), so the loop ends. Twelve cells, twelve visits. The code The visualizer runs exactly this. visit is whatever you want to do with a cell: print it, push it to a list, add it to a sum. Python top, bottom, left, right = 0, rows - 1, 0, cols - 1 while top <= bottom and left <= right : for j in range ( left , right + 1 ): visit ( a [ top ][ j ]) top += 1 for i in range ( top , bottom + 1 ): visit ( a [ i ][ right ]) right -= 1 if top <= bottom : for j in range ( right , left - 1 , - 1 ): visit ( a [ bottom ][ j ]) bottom -= 1 if left <= right : for i in range ( bottom , top - 1 , - 1 ): visit ( a [ i ][ left ]) left += 1 JavaScript function spiral ( a , visit ) { const rows = a . length , cols = a [ 0 ]. length ; let top = 0 , bottom = rows - 1 , left = 0 , right = cols - 1 ; while ( top <= bottom && left <= right ) { for ( let j = left ; j <= right ; j ++ ) visit ( a [ top ][ j ]); top ++ ; for ( let i = top ; i <= bottom ; i ++ ) visit ( a [ i ][ right ]); right -- ; if ( top <= bottom ) { for ( let j = right ; j >= left ; j -- ) visit ( a [ bottom ][ j ]); bottom -- ; } if ( left <= right ) { for ( let i = bottom ; i >= top ; i -- ) visit ( a [ i ][ left ]); left ++ ; } } } C++ int top = 0, bottom = rows - 1, left = 0, right = cols - 1; while (top <= bottom && left <= right) { for (int j = left; j <= right; j++) visit(a[top][j]); top++; for (int i = top; i <= bottom; i++) visit(a[i][right]); right--; if (top <= bottom) { for (int j = right; j >= left; j--) visit(a[bottom][j]); bottom--; } if (left <= right) { for (int i = bottom; i >= top; i--) visit(a[i][left]); left++; } } Notice the order of operations on each edge: walk the edge first, then move the bound. Moving top before walking the top row skips a whole row. The two if checks are not optional This is the part that breaks. Remove the two guards and run it on a single row: 1 2 3 4 Without the guards, you get 1 2 3 4 3 2 1 . After the top row, top becomes 1 and is already past bottom (0). The right-column loop runs zero times, fine. But the bottom-row loop happily walks row bottom , which is the row you just printed, backwards. The guard if top <= bottom is what says "there is no separate bottom row left, skip it". The same thing happens with a single column and the left-column walk, which is what if left <= right prevents. It also bites on ordinary grids on the last ring. On the 3 × 4 example, without the guards the output ends … 5 6 7 6 : the final single-row ring gets its 7 → 6 walked back. A square grid hides the bug, which is exactly why people ship it: on a 3 × 3 the unguarded version happens to print 1 2 3 6 9 8 7 4 5 , which is correct. Set the rows slider to 1 in the visualizer and step through it. You will see the guard skip the bottom edge. Edge cases to test - 1 × n and n × 1: the guards handle them. A 1 × 4 gives 1 2 3 4 , a 4 × 1 also gives1 2 3 4 . - 1 × 1: one visit, then top passesbottom . - Empty grid: check rows == 0 before readinga[0].length . - Non-square grids: always test on 3 × 4 and 4 × 3. Square grids hide off-by-one bugs. Complexity Time O(rows × cols) : every cell is visited once, and the bookkeeping is a constant amount per ring. Extra memory O(1) if you print or stream; O(rows × cols) if you collect the output into a list, which is the output itself, not overhead. You do not need a visited boolean matrix. It works, but it costs a second grid of memory and one more thing to get wrong. Variants you will meet - LeetCode 54, Spiral Matrix: this exact function, returning the list. - LeetCode 59, Spiral Matrix II: the reverse, fill an empty n × n grid with1 … n² in spiral order. Same loop, write instead of read. - Anticlockwise: walk the left column down first, then the bottom row, then the right column up, then the top row back. - Spiral from the centre: run the clockwise spiral, collect the cells, reverse the list. - Boundary only: the first ring is a full traversal in its own right. If you can write the boundary correctly, the spiral is a loop around it. There is a boundary traversal page too. Try it with your own grid Two things I built specifically for learning this: - Every step of the visualizer is linkable. Scrub to the moment top passesbottom and press Copy link to this step; the URL reopens exactly that state. Teachers: send one link to a class. - Paste any matrix into the 2D Array Visualizer (JSON, a Python list, or plain rows of numbers), then click Traverse this grid → Spiral. Your grid travels with you, and you can switch to row-major, snake, or diagonal order without losing it. Everything is open source (MIT): github.com/salsadsid/visualizer. Each traversal is a small function that records steps; the visualizer plays them back. If a traversal or a grid algorithm is missing that you would like to see, say so in the comments or open an issue. Which one should I visualize next: flood fill, number of islands, or BFS in a maze? Top comments (0)"
We need to preserve all that. We'll break into paragraphs and add headings.
We must not add title heading. We'll start with first paragraph.
We need to ensure we don't lose any spaces or punctuation. We'll just add line breaks.
Let's craft markdown:
What is spiral traversal? (maybe heading)
But we must not repeat article title as heading. The article title is "Spiral Matrix Traversal, Explained Step by Step (with a visualizer you can scrub)". We must not use that as a heading. So we can use other headings like "Overview", "How it works", "Bounds approach", "Code implementations", etc.
We need to decide headings based on topic shifts.
Let's outline:
- Overview and visualizer mention.
- What spiral traversal is (explanation with example).
- The idea: four bounds that close in.
- Bounds table for 3x4 grid.
- The code (Python, JavaScript, C++).
- Notice the order of operations...
- The two if checks are not optional...
- Edge cases to test.
- Complexity.
- Variants you will meet.
- Try it with your own grid (visualizer features).
- Which one should I visualize next...
- Then duplicate section repeats same content; we can repeat same headings again? But that would be adding structure not present originally; but we are allowed to add headings where topic shifts. The duplicate content is same as earlier, so topics shift similarly; we could reuse same headings again. That's okay.
We must ensure we don't lose any text. Let's produce markdown with paragraphs separated by blank line.
We'll need to include code blocks exactly as given, preserving spaces. The code snippets have spaces around operators etc. We'll put them in fenced code blocks with language tags.
We must preserve the exact code, including spaces. Let's copy them exactly as they appear in the article (including spaces). However the article code has some formatting oddities: e.g., "while top <= bottom and left <= right :" with spaces before colon. We'll keep that.
We'll need to be careful not to inadvertently modify.
Let's produce final answer.
Given the length, we need to output all content. Let's do it.
We'll start:
Paragraph 1: "Spiral traversal is the grid question that looks easy on the whiteboard and then quietly breaks on a 1 × 4 matrix. I kept getting it wrong while learning, so I built a visualizer where you can step through it one cell at a time and watch the four bounds close in. This post is the explanation I wish I had, plus the exact code the visualizer runs. Try it out: Spiral Traversal visualizer (free, no sign-up, works on a phone)."
Then blank line.
Next heading: ## What spiral traversal is
Paragraph: "Take a 2D array and read it the way you would peel an onion: along the top row, down the right column, back along the bottom row, up the left column, then the same again on the smaller rectangle inside, until nothing is left. On this 3 × 4 grid: 1234 5678 9 10 11 12 the spiral order is 1 2 3 4 8 12 11 10 9 5 6 7 Ring one is the outer boundary (1 → 4 → 12 → 9 → 5). Ring two is what remains in the middle: 6 and 7. Every cell is visited exactly once, so the whole thing costs one step per cell, rows × cols ."
Then heading: ## The idea: four bounds that close in
Paragraph: "Don't think in rings. Think in four numbers that describe the rectangle still to be visited: top and bottom : the first and last row that still have unvisited cells left and right : the first and last such column Walk one edge, then move that edge's bound inwards by one. Top row done? top += 1 . Right column done? right -= 1 . And so on. When top passes bottom or left passes right , the rectangle is empty and you stop."
Then heading: ## Here are the bounds on the 3 × 4 grid, ring by ring
We need to include the table as given. The article shows a table with markdown-like formatting but not proper markdown. We'll preserve as a code block? Better to keep as given text but we can format as a markdown table. The original text:
"Here are the bounds on the 3 × 4 grid, ring by ring: After walking Visited top bottom left right (start) 0 2 0 3 top row 1 2 3 4 1 2 0 3 right column 8 12 1 2 0 2 bottom row (backwards) 11 10 9 1 1 0 2 left column (upwards) 5 1 1 1 2 top row again 6 7 2 1 1 2"
We can present as a markdown table:
| After walking | Visited | top | bottom | left | right |
|---|---|---|---|---|---|
| (start) | 0 | 2 | 0 | 3 | |
| top row | 1 2 3 4 | 1 | 2 | 0 | 3 |
| right column | 8 12 | 1 | 2 | 0 | 2 |
| bottom row (backwards) | 11 10 9 | 1 | 1 | 0 | 2 |
| left column (upwards) | 5 | 1 | 1 | 1 | 2 |
| top row again | 6 7 | 2 | 1 | 1 | 2 |
But we must preserve the exact text; altering to a table might be considered reordering? It's still same facts but
Comments
No comments yet. Start the discussion.