{x}
blog image

Diagonal Traverse II

Given a 2D integer array nums, return all elements of nums in diagonal order as shown in the below images.

 

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

Solution Explanation: Diagonal Traverse II

This problem asks us to traverse a 2D array diagonally and return the elements in the order they appear on the diagonals. The diagonals are traversed from top-left to bottom-right, with elements on the same diagonal appearing consecutively in the output.

Approach:

The key observation is that all elements on the same diagonal share the same sum of their row and column indices (i+j). Diagonals further down (towards the bottom-right) have larger i+j values. Within the same diagonal, elements are ordered by increasing column index (j). This allows us to sort the elements based on these properties.

The algorithm proceeds as follows:

  1. Create a list of tuples: Iterate through the input nums array. For each element nums[i][j], create a tuple (i+j, j, nums[i][j]). This tuple represents the element's diagonal (i+j), its column index (j), and its value.

  2. Sort the tuples: Sort the list of tuples based on the first two elements of each tuple:

    • Primarily by i+j (diagonal index). Elements on the same diagonal will be grouped together.
    • Secondarily by j (column index). Within a diagonal, elements are ordered by increasing column index.
  3. Extract and return values: Finally, extract the third element (the value nums[i][j]) from each sorted tuple and return them as a list.

Time Complexity: O(MN log(MN)), where M is the number of rows and N is the maximum number of columns in nums. This is dominated by the sorting step, which involves sorting M*N tuples.

Space Complexity: O(M*N), to store the tuples.

Code Implementation (Python):

class Solution:
    def findDiagonalOrder(self, nums: List[List[int]]) -> List[int]:
        arr = []
        for i, row in enumerate(nums):
            for j, v in enumerate(row):
                arr.append((i + j, j, v))  # Tuple: (diagonal index, column index, value)
        arr.sort()  # Sorts based on diagonal index then column index
        return [v[2] for v in arr]  # Extracts and returns the values
 

Code Implementation (Java):

import java.util.*;
class Solution {
    public int[] findDiagonalOrder(List<List<Integer>> nums) {
        List<int[]> arr = new ArrayList<>();
        for (int i = 0; i < nums.size(); ++i) {
            for (int j = 0; j < nums.get(i).size(); ++j) {
                arr.add(new int[] {i + j, j, nums.get(i).get(j)});
            }
        }
        Collections.sort(arr, (a, b) -> {
            if (a[0] != b[0]) return a[0] - b[0];
            return a[1] - b[1];
        });
        int[] ans = new int[arr.size()];
        for (int i = 0; i < arr.size(); ++i) {
            ans[i] = arr.get(i)[2];
        }
        return ans;
    }
}

The other languages (C++, Go, TypeScript, C#) follow a similar pattern, creating tuples/arrays, sorting them, and extracting the result. The core logic remains the same across all implementations.