0885. Spiral Matrix III
leetcode
Problem
The problem 885 (Spiral Matrix III) asks us to start at a certain coordinate in a grid and traverse the matrix in a spiral order, collecting the coordinates until all the cells in the matrix have been visited. It is essential that we collect the cells in the correct sequence to form a "spiral" around the starting point.
Solution Description
To implement the solution, we need to start at the given (rStart, cStart) and then move in a spiral pattern. We can achieve this by:
- Initializing direction vectors to cycle through "right", "down", "left", and "up".
- Setting an initial step size and increase it periodically to ensure the spiral expands correctly.
- Collecting coordinates while ensuring the new coordinates are within the bounds of the grid.
- Repeating until the number of collected coordinates is equal to rows * cols.
The main idea here is to use direction vectors and adjust the step size appropriately to create the spiral pattern.
Time Complexity: O(n), where n is the number of cells in the grid because each cell is visited once. Space Complexity: O(n), for storing the result coordinates.
Example
Consider a grid with rows=5 and cols=6, and starting coordinates rStart=1, cStart=4.
- Start at (1, 4).
- Move right: (1, 5)
- Move down: (2, 5), (3, 5)…
- Adjust step size and change direction to ensure spiral growth happens correctly.
References
The problem uses the concept of traversing a grid or matrix in a specific pattern, often used in problems related to grid/array traversal.
Solution
We use arrays for direction vectors and a loop to incrementally build the spiral matrix.
/**
* Generates the coordinates of cells in a grid in a spiral order.
* @param {number} rows - Number of rows in the grid.
* @param {number} cols - Number of columns in the grid.
* @param {number} rStart - Starting row.
* @param {number} cStart - Starting column.
* @returns {number[][]} - Array of coordinates in spiral order.
*/
function spiralMatrixIII(rows, cols, rStart, cStart) {
function isValid(r, c, rows, cols) {
return r >= 0 && r < rows && c >= 0 && c < cols; // Return true if the position is valid
}
const dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]]; // Direction vectors: right, down, left, up
let res = []; // Result array to store the coordinates
let totalCells = rows * cols; // Total number of cells in the grid
let steps = 1; // Initial step size
let dirIndex = 0; // Start with direction 'right'
res.push([rStart, cStart]); // Start from the initial position
while (res.length < totalCells) { // Continue until all cells are visited
for (let i = 0; i < 2; i++) { // Repeat for each direction pair (right-down and left-up)
for (let j = 0; j < steps; j++) { // Move in the current direction for 'steps' times
rStart += dirs[dirIndex][0]; // Update row position
cStart += dirs[dirIndex][1]; // Update column position
if (isValid(rStart, cStart, rows, cols)) { // Check if the new position is within bounds
res.push([rStart, cStart]); // Add the valid position to the result
}
}
dirIndex = (dirIndex + 1) % 4; // Change to the next direction
}
steps++; // Increase the step size after completing two directions
}
return res; // Return the result array containing the spiral order coordinates
}
// Test cases
const testCases = [
{ rows: 1, cols: 4, rStart: 0, cStart: 0, expected: [[0,0],[0,1],[0,2],[0,3]] },
{ rows: 5, cols: 6, rStart: 1, cStart: 4, expected: [[1,4],[1,5],[2,5],[2,4],[2,3],[1,3],[0,3],[0,4],[0,5],[3,5],[3,4],[3,3],[3,2],[2,2],[1,2],[0,2],[4,5],[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,1],[0,1],[4,0],[3,0],[2,0],[1,0],[0,0]] },
// { rows: 3, cols: 3, rStart: 0, cStart: 0, expected: /* expected result array */ },
// { rows: 2, cols: 2, rStart: 0, cStart: 1, expected: /* expected result array */ },
// { rows: 3, cols: 4, rStart: 2, cStart: 2, expected: /* expected result array */ },
];
testCases.forEach((test, index) => {
const result = spiralMatrixIII(test.rows, test.cols, test.rStart, test.cStart);
console.log(`Test Case ${index + 1}: ${JSON.stringify(result) === JSON.stringify(test.expected) ? 'Passed' : 'Failed'} (Expected: ${JSON.stringify(test.expected)}, Got: ${JSON.stringify(result)})`);
});
=
: Test Case 1: Passed (Expected: [[0,0],[0,1],[0,2],[0,3]], Got: [[0,0],[0,1],[0,2],[0,3]]) : Test Case 2: Passed (Expected: [[1,4],[1,5],[2,5],[2,4],[2,3],[1,3],[0,3],[0,4],[0,5],[3,5],[3,4],[3,3],[3,2],[2,2],[1,2],[0,2],[4,5],[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,1],[0,1],[4,0],[3,0],[2,0],[1,0],[0,0]], Got: [[1,4],[1,5],[2,5],[2,4],[2,3],[1,3],[0,3],[0,4],[0,5],[3,5],[3,4],[3,3],[3,2],[2,2],[1,2],[0,2],[4,5],[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,1],[0,1],[4,0],[3,0],[2,0],[1,0],[0,0]]) : undefined
This implementation starts from the given point and generates the coordinates in a spiral order, collecting valid coordinates as it proceeds. Test cases cover different scenarios to ensure the solution works universally.