class Solution:
def diagonalSort(self, mat):
from collections import defaultdict
m, n = len(mat), len(mat[0])
diags = defaultdict(list)
# Collect elements of each diagonal
for i in range(m):
for j in range(n):
diags[i - j].append(mat[i][j])
# Sort each diagonal
for key in diags:
diags[key].sort(reverse=True)
# Place sorted elements back
for i in range(m):
for j in range(n):
mat[i][j] = diags[i - j].pop()
return mat
class Solution {
public:
vector<vector<int>> diagonalSort(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
unordered_map<int, vector<int>> diags;
// Collect elements of each diagonal
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
diags[i - j].push_back(mat[i][j]);
}
}
// Sort each diagonal
for (auto &p : diags) {
sort(p.second.begin(), p.second.end(), greater<int>());
}
// Place sorted elements back
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
mat[i][j] = diags[i - j].back();
diags[i - j].pop_back();
}
}
return mat;
}
};
class Solution {
public int[][] diagonalSort(int[][] mat) {
int m = mat.length, n = mat[0].length;
Map<Integer, List<Integer>> diags = new HashMap<>();
// Collect elements of each diagonal
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
diags.computeIfAbsent(i - j, k -> new ArrayList<>()).add(mat[i][j]);
}
}
// Sort each diagonal
for (List<Integer> diag : diags.values()) {
diag.sort(Comparator.reverseOrder());
}
// Place sorted elements back
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
mat[i][j] = diags.get(i - j).remove(diags.get(i - j).size() - 1);
}
}
return mat;
}
}
var diagonalSort = function(mat) {
const m = mat.length, n = mat[0].length;
const diags = {};
// Collect elements of each diagonal
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
const key = i - j;
if (!(key in diags)) diags[key] = [];
diags[key].push(mat[i][j]);
}
}
// Sort each diagonal
for (const key in diags) {
diags[key].sort((a, b) => b - a);
}
// Place sorted elements back
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
const key = i - j;
mat[i][j] = diags[key].pop();
}
}
return mat;
};
Given a 2D integer matrix mat
of size m x n
, your task is to sort each diagonal of the matrix in ascending order, where a diagonal runs from the top-left to the bottom-right. After sorting, the matrix should be updated in-place so that each diagonal contains its sorted values. Each element must remain within its original diagonal, and every diagonal must be sorted independently. There is only one valid solution for each input, and you must not reuse or move elements between different diagonals.
The core challenge is to sort elements that are connected diagonally, not row-wise or column-wise. At first glance, a brute-force approach might try to extract each diagonal, sort it, and put it back. However, we need an efficient way to map each cell to its diagonal and process all diagonals systematically.
Thinking further, we realize all elements on the same diagonal share the same difference between their row and column indices (i - j
). This makes it easy to group elements by diagonal. By leveraging this property, we can collect, sort, and redistribute diagonal elements with minimal overhead.
The main optimization is to use a hash map (dictionary) to group elements by their diagonal key, sort them, and then write them back to their original positions.
To solve the problem efficiently, we follow these steps:
(i, j)
in the matrix, compute the diagonal key as i - j
.mat[i][j]
in a hash map or dictionary under the key i - j
.pop()
from the list for fast removal of the smallest element.(i, j)
, assign it the next sorted value from its diagonal's list.This approach ensures that each diagonal is sorted independently and that all elements remain within their original diagonals.
Consider the input matrix:
[[3, 3, 1, 1],
[2, 2, 1, 2],
[1, 1, 1, 2]]
i - j = 0
): [3, 2, 1]
The final sorted matrix is:
[[1, 1, 1, 1],
[1, 2, 2, 2],
[1, 2, 3, 3]]
Each diagonal is now sorted in ascending order, and elements remain within their original diagonals.
Brute-force approach:
The key insight is that all cells on the same diagonal share the same i - j
value, allowing us to group and process diagonals efficiently. By collecting elements into a hash map, sorting, and writing them back, we achieve an elegant and efficient solution that works for any matrix size. This approach avoids unnecessary complexity and leverages simple data structures for clarity and speed.