🧠
Optimal (Index Formula Without Direction Flag)
💡 This approach uses a mathematical formula to compute the exact element indices in the diagonal traversal order, eliminating the need for direction flags or conditionals.
Intuition
Each diagonal is identified by the sum of indices (d = r + c). For each diagonal, the elements can be accessed by calculating row and column indices directly using formulas that depend on whether the diagonal is even or odd.
Algorithm
- Calculate total diagonals as m + n - 1.
- For each diagonal d, determine the start and end indices of elements in that diagonal.
- If d is even, traverse the diagonal from bottom to top; if odd, from top to bottom using index formulas.
- Append elements directly to the result array.
💡 The key is to derive the correct formulas for row and column indices for each diagonal and direction.
from typing import List
def findDiagonalOrder(mat: List[List[int]]) -> List[int]:
if not mat or not mat[0]:
return []
m, n = len(mat), len(mat[0])
result = []
for d in range(m + n - 1):
# Determine the start and end row indices for this diagonal
r_start = max(0, d - n + 1)
r_end = min(d, m - 1)
if d % 2 == 0:
# Even diagonal: traverse from r_end down to r_start
for r in range(r_end, r_start - 1, -1):
c = d - r
result.append(mat[r][c])
else:
# Odd diagonal: traverse from r_start up to r_end
for r in range(r_start, r_end + 1):
c = d - r
result.append(mat[r][c])
return result
# Driver code
if __name__ == '__main__':
matrix = [[1,2,3],[4,5,6],[7,8,9]]
print(findDiagonalOrder(matrix)) # Expected: [1,2,4,7,5,3,6,8,9]
Line Notes
r_start = max(0, d - n + 1)Calculate the first row index in the diagonal
r_end = min(d, m - 1)Calculate the last row index in the diagonal
if d % 2 == 0:Traverse diagonals in different directions based on parity
c = d - rColumn index is derived from diagonal index minus row index
import java.util.*;
public class DiagonalTraverse {
public static int[] findDiagonalOrder(int[][] mat) {
if (mat == null || mat.length == 0) return new int[0];
int m = mat.length, n = mat[0].length;
int[] result = new int[m * n];
int idx = 0;
for (int d = 0; d < m + n - 1; d++) {
int rStart = Math.max(0, d - n + 1);
int rEnd = Math.min(d, m - 1);
if (d % 2 == 0) {
for (int r = rEnd; r >= rStart; r--) {
int c = d - r;
result[idx++] = mat[r][c];
}
} else {
for (int r = rStart; r <= rEnd; r++) {
int c = d - r;
result[idx++] = mat[r][c];
}
}
}
return result;
}
public static void main(String[] args) {
int[][] matrix = {{1,2,3},{4,5,6},{7,8,9}};
System.out.println(Arrays.toString(findDiagonalOrder(matrix)));
}
}
Line Notes
int rStart = Math.max(0, d - n + 1);Calculate starting row index for diagonal d
int rEnd = Math.min(d, m - 1);Calculate ending row index for diagonal d
if (d % 2 == 0)Traverse diagonals in reverse order for even d
int c = d - r;Column index derived from diagonal and row indices
#include <iostream>
#include <vector>
using namespace std;
vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
if (mat.empty() || mat[0].empty()) return {};
int m = mat.size(), n = mat[0].size();
vector<int> result;
for (int d = 0; d < m + n - 1; d++) {
int rStart = max(0, d - n + 1);
int rEnd = min(d, m - 1);
if (d % 2 == 0) {
for (int r = rEnd; r >= rStart; r--) {
int c = d - r;
result.push_back(mat[r][c]);
}
} else {
for (int r = rStart; r <= rEnd; r++) {
int c = d - r;
result.push_back(mat[r][c]);
}
}
}
return result;
}
int main() {
vector<vector<int>> matrix = {{1,2,3},{4,5,6},{7,8,9}};
vector<int> res = findDiagonalOrder(matrix);
for (int num : res) cout << num << " ";
cout << endl;
return 0;
}
Line Notes
int rStart = max(0, d - n + 1);Calculate first row index for diagonal d
int rEnd = min(d, m - 1);Calculate last row index for diagonal d
if (d % 2 == 0)Traverse diagonals in reverse order for even d
int c = d - r;Compute column index from diagonal and row
function findDiagonalOrder(mat) {
if (!mat || mat.length === 0) return [];
const m = mat.length, n = mat[0].length;
const result = [];
for (let d = 0; d < m + n - 1; d++) {
const rStart = Math.max(0, d - n + 1);
const rEnd = Math.min(d, m - 1);
if (d % 2 === 0) {
for (let r = rEnd; r >= rStart; r--) {
const c = d - r;
result.push(mat[r][c]);
}
} else {
for (let r = rStart; r <= rEnd; r++) {
const c = d - r;
result.push(mat[r][c]);
}
}
}
return result;
}
// Test
const matrix = [[1,2,3],[4,5,6],[7,8,9]];
console.log(findDiagonalOrder(matrix)); // [1,2,4,7,5,3,6,8,9]
Line Notes
const rStart = Math.max(0, d - n + 1);Calculate starting row index for diagonal d
const rEnd = Math.min(d, m - 1);Calculate ending row index for diagonal d
if (d % 2 == 0)Traverse diagonals in reverse order for even d
const c = d - r;Column index derived from diagonal and row indices
Each element is visited once and appended directly without extra overhead or direction flags.
💡 This approach is clean and efficient, suitable for large matrices where clarity and speed matter.
Interview Verdict: Accepted
This is the most optimal and elegant approach to code in interviews for this problem.