Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
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 <= 1051 <= nums[i].length <= 1051 <= sum(nums[i].length) <= 1051 <= nums[i][j] <= 105Problem summary: Given a 2D integer array nums, return all elements of nums in diagonal order as shown in the below images.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
[[1,2,3],[4,5,6],[7,8,9]]
[[1,2,3,4,5],[6,7],[8],[9,10,11],[12,13,14,15,16]]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1424: Diagonal Traverse II
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)});
}
}
arr.sort((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
int[] ans = new int[arr.size()];
for (int i = 0; i < arr.size(); ++i) {
ans[i] = arr.get(i)[2];
}
return ans;
}
}
// Accepted solution for LeetCode #1424: Diagonal Traverse II
func findDiagonalOrder(nums [][]int) []int {
arr := [][]int{}
for i, row := range nums {
for j, v := range row {
arr = append(arr, []int{i + j, j, v})
}
}
sort.Slice(arr, func(i, j int) bool {
if arr[i][0] == arr[j][0] {
return arr[i][1] < arr[j][1]
}
return arr[i][0] < arr[j][0]
})
ans := []int{}
for _, v := range arr {
ans = append(ans, v[2])
}
return ans
}
# Accepted solution for LeetCode #1424: Diagonal Traverse II
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))
arr.sort()
return [v[2] for v in arr]
// Accepted solution for LeetCode #1424: Diagonal Traverse II
struct Solution;
impl Solution {
fn find_diagonal_order(nums: Vec<Vec<i32>>) -> Vec<i32> {
let n = nums.len();
let mut rows: Vec<Vec<i32>> = vec![];
for i in 0..n {
for (j, &v) in nums[i].iter().enumerate() {
let k = i + j;
if rows.len() == k {
rows.push(vec![]);
}
rows[k].push(v);
}
}
rows.into_iter().flat_map(|q| q.into_iter().rev()).collect()
}
}
#[test]
fn test() {
let nums = vec_vec_i32![[1, 2, 3], [4, 5, 6], [7, 8, 9]];
let res = vec![1, 4, 2, 7, 5, 3, 8, 6, 9];
assert_eq!(Solution::find_diagonal_order(nums), res);
let nums = vec_vec_i32![
[1, 2, 3, 4, 5],
[6, 7],
[8],
[9, 10, 11],
[12, 13, 14, 15, 16]
];
let res = vec![1, 6, 2, 8, 7, 3, 9, 4, 12, 10, 5, 13, 11, 14, 15, 16];
assert_eq!(Solution::find_diagonal_order(nums), res);
let nums = vec_vec_i32![[1, 2, 3], [4], [5, 6, 7], [8], [9, 10, 11]];
let res = vec![1, 4, 2, 5, 3, 8, 6, 9, 7, 10, 11];
assert_eq!(Solution::find_diagonal_order(nums), res);
let nums = vec_vec_i32![[1, 2, 3, 4, 5, 6]];
let res = vec![1, 2, 3, 4, 5, 6];
assert_eq!(Solution::find_diagonal_order(nums), res);
}
// Accepted solution for LeetCode #1424: Diagonal Traverse II
function findDiagonalOrder(nums: number[][]): number[] {
const arr: number[][] = [];
for (let i = 0; i < nums.length; ++i) {
for (let j = 0; j < nums[i].length; ++j) {
arr.push([i + j, j, nums[i][j]]);
}
}
arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]));
return arr.map(x => x[2]);
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.