Diagonal Traverse II

Updated on 22 May, 2025
Diagonal Traverse II header image

Problem Statement

The task is to return all elements of a given 2D integer array nums according to a specific diagonal traversal pattern. Diagonal traversal involves moving along the diagonals of the array matrix, starting from the top left corner, progressing diagonally downwards to the right, and then continuing the pattern until all elements are covered.

Examples

Example 1

Input:

nums = [[1,2,3],[4,5,6],[7,8,9]]

Output:

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

Example 2

Input:

nums = [[1,2,3,4,5],[6,7],[8],[9,10,11],[12,13,14,15,16]]

Output:

[1,6,2,8,7,3,9,4,12,10,5,13,11,14,15,16]

Constraints

  • 1 <= nums.length <= 105
  • 1 <= nums[i].length <= 105
  • 1 <= sum(nums[i].length) <= 105
  • 1 <= nums[i][j] <= 105

Approach and Intuition

Given the problem's requirements, our objective is to systematically traverse the 2D array in diagonals, starting from the element at the top-left. Here’s a detailed breakdown of the approach:

  1. Initialize a dictionary or a list to gather elements by their corresponding diagonals. Each key in the dictionary can represent a diagonal, and the values are the elements in that diagonal.
  2. Traverse through the array and place each element into the dictionary based on the sum of their index. Elements nums[i][j] will go into the diagonal labeled (i + j).
  3. Each diagonal should be processed for the output - diagonals with an even key will keep the order as is, and diagonals with an odd key will reverse their order. This alternates the diagonals' direction as required.
  4. Finally, concatenate all diagnostics sequentially based on their key values to get the final list.

Given the examples provided:

  • For the first example, starting with the first element [0][0], we move diagonally to [1][0] and [0][1], and so on, finally the traversal fits perfectly into the requirements by the method of alternating the direction and using indexed placement.
  • For the second example, the different lengths of the rows introduce variance in diagonal lengths, yet the approach using indexed summation (i+j) suitably categorizes each into the right diagonal sequence.

This method efficiently accumulates elements and achieves the diagonal order output using the constraints and properties established:

  • The array dimensions are flexible (with given constraints on maximum size).
  • The values are within the specified range and don’t affect the traversal order, but it's crucial to implement the solution to manage space complexity due to potentially large sizes.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    vector<int> traverseDiagonally(vector<vector<int>>& matrix) {
        queue<pair<int, int>> traversalQueue;
        traversalQueue.push({0, 0});
        vector<int> result;
        
        while (!traversalQueue.empty()) {
            auto [r, c] = traversalQueue.front();
            traversalQueue.pop();
            result.push_back(matrix[r][c]);
            
            if (c == 0 && r + 1 < matrix.size()) {
                traversalQueue.push({r + 1, c});
            }
            
            if (c + 1 < matrix[r].size()) {
                traversalQueue.push({r, c + 1});
            }
        }
        
        return result;
    }
};

In this solution for the "Diagonal Traverse II" problem using C++, the approach involves using a queue to manage the traversal of a given matrix diagonally. Here's a breakdown of how the implementation works:

  • A queue is initialized to keep track of matrix positions during traversal. The top-left position (0, 0) is added initially to start the process.
  • An empty vector named result is prepared to store the values as they are encountered.
  • The queue is processed in a loop until it is empty. In each iteration:
    • The first position in the queue is dequeued to get the current row (r) and column (c).
    • The value at this position in the matrix is added to the result vector.
    • The logic then considers the next diagonal steps by evaluating the boundaries of the matrix. It checks for movement in two possible directions:
      1. Downward (next row, same column): Push the position (r + 1, c) to the queue if the next row exists within the matrix bounds.
      2. Rightward (same row, next column): Push the position (r, c + 1) to the queue if the next column exists within the current row boundaries.
  • This loop continues until all possible paths in the matrix are explored and all the positions on the diagonals visited are pushed to the result vector.
  • Finally, the vector result is returned, containing the values of the matrix as traversed diagonally according to the devised queuing mechanism.

This approach effectively captures diagonal traversal in a structured matrix, ensuring every potential “next step” is explored by adhering to the matrix’s boundary constraints.

java
class Solution {
    public int[] diagonalTraversal(List<List<Integer>> matrix) {
        Queue<Pair<Integer, Integer>> processingQueue = new LinkedList();
        processingQueue.offer(new Pair(0, 0));
        List<Integer> resultList = new ArrayList();
        
        while (!processingQueue.isEmpty()) {
            Pair<Integer, Integer> current = processingQueue.poll();
            int currentRow = current.getKey();
            int currentCol = current.getValue();
            resultList.add(matrix.get(currentRow).get(currentCol));
            
            if (currentCol == 0 && currentRow + 1 < matrix.size()) {
                processingQueue.offer(new Pair(currentRow + 1, currentCol));
            }
            
            if (currentCol + 1 < matrix.get(currentRow).size()) {
                processingQueue.offer(new Pair(currentRow, currentCol + 1));
            }
        }
        
        int[] diagonalOrder = new int[resultList.size()];
        int idx = 0;
        for (int value : resultList) {
            diagonalOrder[idx] = value;
            idx++;
        }
        
        return diagonalOrder;
    }
}

The given Java code solves the problem of traversing a list of lists (representing a matrix) diagonally. The solution uses a breadth-first search (BFS) approach embodied by a queue to manage how each element is visited. Below is a breakdown of the solution workflow:

  • Initialize a queue to manage pairs of indexes representing positions in the matrix.
  • Start with the top-left corner of the matrix, the position (0,0).
  • Utilize a while loop to process each element until the queue is empty. In each iteration:
    • Dequeue a pair to determine the current position.
    • Store the value at the current position in the resultList.
    • If feasible (without going out of bounds), enqueue the position directly below (next row, same column).
    • Similarly, enqueue the position to the right (same row, next column), provided it is valid.
  • After processing all elements, convert the resultList into an array for the final output.

This method ensures that the matrix is traversed in a zigzag or diagonal pattern, consequently adding those elements first whose row and column indices sum is smaller, simulating a diagonal traversal from the top left to the bottom right of the matrix. The use of a queue ensures each cell is processed in the correct sequence without backtracking.

python
class Solution:
    def diagonalTraversal(self, matrix: List[List[int]]) -> List[int]:
        q = deque([(0, 0)])
        result = []
        
        while q:
            r, c = q.popleft()
            result.append(matrix[r][c])
            
            if c == 0 and r + 1 < len(matrix):
                q.append((r + 1, c))
                
            if c + 1 < len(matrix[r]):
                q.append((r, c + 1))
        
        return result

In this Python3 solution, the function diagonalTraversal navigates a two-dimensional matrix diagonally, collecting values in a sequence. Ensure you provide the correct matrix input, which should be a list of lists of integers. This traversal strategy is achieved using a deque for efficient element insertion and removal.

Here's a breakdown of the code functionality:

  • Initialize a deque q starting with the top-left corner of the matrix (0, 0).
  • Create an empty list result that will store integers in the sequence of diagonal traversal.
  • Use a while loop that continues as long as there are elements in q.
    • Remove the element at the front of the deque (popleft) which gives the current row and column indices, r and c.
    • Append the current matrix value matrix[r][c] to result.
    • If the current column is zero and there's a row below, append that next row's initial element to q.
    • If there's another column in the current row, append that next column's element to q.

The function ultimately returns the result list, which includes the matrix elements in the order of their diagonal traversal. This approach is robust and handles different matrix shapes, ensuring diagonal elements are processed correctly.

Comments

No comments yet.