
Problem Statement
Given two integers, m
and n
, which describe the dimensions of a matrix, and a singly linked list of integers representing the head of the list, the objective is to construct an m x n
matrix filled with the integers from the linked list in a spiral or clockwise pattern, starting from the top-left corner of the matrix. If the linked list contains fewer elements than the matrix can hold, the remaining matrix entries should be filled with -1
. The task is to return this newly generated matrix.
Examples
Example 1
Input:
m = 3, n = 5, head = [3,0,2,6,8,1,7,9,4,2,5,5,0]
Output:
[[3,0,2,6,8],[5,0,-1,-1,1],[5,2,4,9,7]]
Explanation:
The diagram above shows how the values are printed in the matrix. Note that the remaining spaces in the matrix are filled with -1.
Example 2
Input:
m = 1, n = 4, head = [0,1,2]
Output:
[[0,1,2,-1]]
Explanation:
The diagram above shows how the values are printed from left to right in the matrix. The last space in the matrix is set to -1.
Constraints
1 <= m, n <= 105
1 <= m * n <= 105
- The number of nodes in the list is in the range
[1, m * n]
. 0 <= Node.val <= 1000
Approach and Intuition
To fill a matrix in a spiral order from a linked list, we follow these steps:
Intialize an
m x n
matrix filled with-1
.Define movement directions as right, down, left, and up to facilitate the spiral pattern:
- right:
(0, 1)
- down:
(1, 0)
- left:
(0, -1)
- up:
(-1, 0)
- right:
Initialize your starting point at the top-left of the matrix and set your initial direction to 'right'.
Iterate through each element of the linked list:
- Place the current element of the linked list into the current position of the matrix.
- Attempt to move in the current direction.
- If the next position is either out of bounds or already filled (not
-1
), change direction:- Right turns to down
- Down turns to left
- Left turns to up
- Up turns to right
- Continue this until all elements of the linked list are placed in the matrix.
Any positions in the matrix that are not filled by elements from the linked list remain as
-1
, indicating unused slots.
This approach leverages both the traversal of a linked list and a systematic way to fill arrays in a spiral pattern, managing boundaries and directions effectively to achieve the desired matrix layout. The handling of edge cases is particularly important, such as when the matrix dimensions are significantly larger than the number of elements in the linked list. Given these constraints and steps, the proposed method provides a systematic solution to the problem, ensuring no index errors or unfilled entries are overlooked.
Solutions
- C++
class Solution {
public:
vector<vector<int>> generateSpiral(int rows, int cols, ListNode* listHead) {
int x = 0, y = 0, directionIndex = 0,
directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
vector<vector<int>> grid(rows, vector<int>(cols, -1));
for (; listHead != nullptr; listHead = listHead->next) {
grid[x][y] = listHead->val;
int nextX = x + directions[directionIndex][0], nextY = y + directions[directionIndex][1];
if (nextX < 0 || nextY < 0 || nextX >= rows || nextY >= cols || grid[nextX][nextY] != -1)
directionIndex = (directionIndex + 1) % 4;
x += directions[directionIndex][0];
y += directions[directionIndex][1];
}
return grid;
}
};
In the given C++ code, you create a matrix and fill it in a spiral order using values from a singly-linked list. Here's a breakdown of the process:
Initialization: Start by defining initial variables for managing current position
(x, y)
in the matrix and the direction of movementdirectionIndex
. Matrix dimensions are represented byrows
andcols
. Initialize a matrixgrid
filled with-1
, which denotes unfilled entries.Direction Control: Use a
directions
array to handle the right, down, left, and up movements respectively. This array helps in updating positions as you traverse through the matrix in a spiral.Linked List Iteration: Traverse through the linked list using a loop. In each iteration:
- Place the current node's value in the
grid
at the current position(x, y)
. - Calculate
nextX
andnextY
to predict the next position. - Check if the next position goes out of matrix bounds or has already been filled. If so, update
directionIndex
to change the direction. - Update
(x, y)
to move to the next position as dictated by the potentially updated direction.
- Place the current node's value in the
Output: After traversing the entire linked list, return the
grid
which now contains the linked list values arranged in a spiral format.
This function efficiently maps linked list values into a 2D matrix structure, while properly maintaining the directional changes needed to achieve a spiral order traversal. Remember that if the list has more elements than rows * cols
, the extra elements will not be placed in the grid, and if it has fewer elements, some positions in the matrix will remain as the initialized -1
value.
- Java
class Solution {
public int[][] generateSpiral(int rows, int cols, ListNode startNode) {
// Directory vectors for right, down, left, up
int x = 0, y = 0, directionIndex = 0, dirs[][] = {
{ 0, 1 },
{ 1, 0 },
{ 0, -1 },
{ -1, 0 }
};
int[][] spiral = new int[rows][cols];
for (int[] line : spiral) {
Arrays.fill(line, -1);
}
while (startNode != null) {
spiral[x][y] = startNode.val;
int nextX = x + dirs[directionIndex][0], nextY = y + dirs[directionIndex][1];
// Check boundaries and filled cells to decide when to turn
if (
nextX < 0 ||
nextY < 0 ||
nextX >= rows ||
nextY >= cols ||
spiral[nextX][nextY] != -1
) directionIndex = (directionIndex + 1) % 4;
x += dirs[directionIndex][0];
y += dirs[directionIndex][1];
startNode = startNode.next;
}
return spiral;
}
}
The Java method generateSpiral(int rows, int cols, ListNode startNode)
is structured to generate a matrix in a spiral arrangement using values from a singly linked list. The method employs directional movements (right, down, left, up) to fill the matrix. The output from each node in the linked list is filled into the matrix spirally from the top left (0,0 position) based on availability and boundary conditions.
Here are the fundamental steps undertaken in this method:
Initialize the starting point at the top-left corner of the matrix and a direction index to manage current movement direction using an array of direction vectors.
Fill the matrix initially with a placeholder value (in this case, -1) to mark cells which have not been filled yet.
Traverse through the linked list. For each node:
- Place the current node's value at the current matrix position.
- Attempt to move in the current direction. If the next position is out of bounds or already filled, then change direction clockwise.
- Update positions accordingly and move to the next node in the linked list.
Continue this process until all nodes in the linked list are exhausted.
Return the matrix as the final output.
This algorithm efficiently fills a matrix in a spiraling pattern, dynamically adjusting directions based on boundary conditions and already filled positions even as it iterates through a potentially long linked list.
- Python
class Solution:
def generate_spiral(self, rows: int, cols: int, node: "ListNode") -> List[List[int]]:
x = 0
y = 0
current_dir = 0
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
matrix = [[-1 for _ in range(cols)] for _ in range(rows)]
while node is not None:
matrix[x][y] = node.val
next_x = x + directions[current_dir][0]
next_y = y + directions[current_dir][1]
if next_x < 0 or next_x >= rows or next_y < 0 or next_y >= cols or matrix[next_x][next_y] != -1:
current_dir = (current_dir + 1) % 4
x += directions[current_dir][0]
y += directions[current_dir][1]
node = node.next
return matrix
The provided Python function generate_spiral
in the Solution
class constructs a matrix based on values from a linked list, filling the matrix in a spiral order. Here's a breakdown of how the function works:
- Initialize the starting point at the top-left of the matrix (0,0) and set the initial direction to 'right'.
- Create a direction array to facilitate movement in right, down, left, and up directions sequentially.
- Construct an empty matrix initialized with
-1
, signaling unfilled cells. - Use a while loop to iterate through the linked list until all nodes are processed:
- Place the current node's value in the matrix at the current position.
- Calculate the next position based on the current direction.
- If the next position is out of bounds or the cell is already filled, change direction clockwise.
- Move to the next position and proceed to the next node in the list.
- Return the filled matrix after all nodes are placed.
This solution ensures that the matrix is filled in a spiral pattern starting from the top left and spiraling inward until all values from the linked list are exhausted or the matrix is fully filled.
No comments yet.