将矩阵按对角线排序
难度:
标签:
题目描述
矩阵对角线 是一条从矩阵最上面行或者最左侧列中的某个元素开始的对角线,沿右下方向一直到矩阵末尾的元素。例如,矩阵 mat
有 6
行 3
列,从 mat[2][0]
开始的 矩阵对角线 将会经过 mat[2][0]
、mat[3][1]
和 mat[4][2]
。
给你一个 m * n
的整数矩阵 mat
,请你将同一条 矩阵对角线 上的元素按升序排序后,返回排好序的矩阵。
示例 1:
输入:mat = [[3,3,1,1],[2,2,1,2],[1,1,1,2]] 输出:[[1,1,1,1],[1,2,2,2],[1,2,3,3]]
示例 2:
输入:mat = [[11,25,66,1,69,7],[23,55,17,45,15,52],[75,31,36,44,58,8],[22,27,33,25,68,4],[84,28,14,11,5,50]] 输出:[[5,17,4,1,52,7],[11,11,25,45,8,69],[14,23,25,44,58,15],[22,27,31,36,50,66],[84,28,75,33,55,68]]
提示:
m == mat.length
n == mat[i].length
1 <= m, n <= 100
1 <= mat[i][j] <= 100
代码结果
运行时间: 28 ms, 内存: 16.3 MB
/*
* 思路:
* 1. 使用流(Stream)遍历矩阵的每条对角线,记录对角线上的元素。
* 2. 对对角线上的元素进行排序。
* 3. 将排序后的元素放回矩阵相应的位置。
*/
import java.util.*;
import java.util.stream.Collectors;
public class Solution {
public int[][] diagonalSort(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
// 处理左下到右上的对角线
for (int i = 0; i < m; i++) {
sortDiagonal(mat, i, 0, m, n);
}
// 处理上到右下的对角线
for (int j = 1; j < n; j++) {
sortDiagonal(mat, 0, j, m, n);
}
return mat;
}
private void sortDiagonal(int[][] mat, int row, int col, int m, int n) {
List<Integer> diagonal = new ArrayList<>();
int r = row, c = col;
while (r < m && c < n) {
diagonal.add(mat[r][c]);
r++;
c++;
}
diagonal = diagonal.stream().sorted().collect(Collectors.toList());
r = row;
c = col;
int index = 0;
while (r < m && c < n) {
mat[r][c] = diagonal.get(index++);
r++;
c++;
}
}
}
解释
方法:
该题解通过对每个对角线上的元素进行收集、排序和重新放置来解决问题。首先,定义一个辅助函数 helpSort 来处理从特定起点 (startI, startJ) 开始的对角线元素。该函数首先遍历对应的对角线,收集所有元素到列表 l 中。然后对列表 l 进行排序,之后将排序后的元素重新赋值回矩阵的对应位置。对于矩阵的每个可能的对角线起点,分别调用 helpSort 函数。对角线的起点分两部分:一部分是矩阵的第一行每个元素作为起点,另一部分是矩阵的第一列除第一个元素外的每个元素作为起点。
时间复杂度:
O((m + n) * min(m, n) * log(min(m, n)))
空间复杂度:
O(min(m, n))
代码细节讲解
🦆
在 helpSort 函数中,如果对角线的长度大于数组的长度,如何确保不会出现索引越界的错误?
▷🦆
你是如何确定对角线上元素的起点的?对于边界条件,如何处理矩阵的最后一行或最后一列?
▷🦆
对角线上的元素排序后重新放置时,为什么可以保证不会影响到其他对角线的元素排序?
▷🦆
在实际操作中,排序每个对角线是否会引入重复排序的问题,尤其是在对角线相交的情况下?
▷