按对角线进行矩阵排序-LeetCode
3446. 按对角线进行矩阵排序
🎯 问题描述
描述:
给你一个大小为 n x m 的整数矩阵 grid。
请你返回一个经过调整的矩阵,调整规则如下:
- 左下角三角形(包括主对角线):该区域内的每一条对角线(从左上到右下方向)按非递增(降序)顺序排序。
- 右上角三角形:该区域内的每一条对角线按非递减(升序)顺序排序。
说明:
- 这是一个坐标变换结合分组排序的问题。
- 核心策略:
- 利用数学公式将二维坐标映射到一维对角线索引。
- 通过枚举对角线标识符
k来遍历所有副对角线。 - 提取对角线元素 -> 排序 -> 写回矩阵。
- 排序规则:根据对角线起始位置动态决定排序方向。
- 示例:
- 示例 1:
1 | 输入:grid = |
💻 解题思路
思路1:坐标映射 + 数学边界推导
核心逻辑
- 枚举副对角线:
- 副对角线(右上到左下方向)的特征是坐标满足线性关系
i - j = k - m。 - 通过变量
k(范围1到m+n-1) 来枚举所有可能的副对角线。
- 副对角线(右上到左下方向)的特征是坐标满足线性关系
- 精确计算边界:
min_j = max(0, n - k):确保行下标i在有效范围内。max_j = min(m - 1, n - 1 + m - k):确保列下标j在有效范围内。
- 动态排序规则:
a.sort(reverse = min_j == 0):- 当
min_j == 0时,对角线从第一行开始,执行降序排序。 - 当
min_j > 0时,对角线从第一列开始,执行升序排序。
- 当
- 原地写回:
- 利用
zip将排序后的值和对应的列下标配对,直接写回grid。 - 行下标通过公式
k + j - m还原。
- 利用
代码实现
1 | class Solution: |
📊 性能分析
- 时间复杂度:
- 其中 是对角线的平均长度。
- 需要遍历 条对角线。
- 每条对角线的排序耗时 ,其中 是该对角线的长度。
- 总体复杂度为 。
- 空间复杂度:
- 需要一个临时数组
a来存储对角线元素,其最大长度为矩阵的最短边。
- 需要一个临时数组
思考
- 坐标变换的数学原理:
- 副对角线的特点是行标与列标之差为定值。
- 代码中使用了
i = k - m + j,变换后得i - j = k - m。 - 令 ,则
i - j = C。随着k的变化,我们遍历了所有可能的i-j差值,从而覆盖了所有副对角线。
- 边界计算的推导:
- 需要保证计算出的行
i和列j都在矩阵范围内。 - 由
0 <= i < n和i = k - m + j,可得0 <= k - m + j < n。 - 移项得
m - k <= j < n + m - k。 - 结合
0 <= j < m,取交集即可得到min_j和max_j的公式。
- 需要保证计算出的行
- 排序方向的逻辑:
- 代码中的
reverse=(min_j == 0)是一个非常巧妙的写法。 - 当
min_j == 0时,意味着列坐标可以从 0 开始,这通常对应于从第一行出发的对角线(右上部分)。 - 当
min_j > 0时,意味着列坐标必须大于 0,这通常对应于从第一列出发的对角线(左下部分)。
- 代码中的
- 代码的健壮性:
- 使用
zip进行写回操作非常 Pythonic,避免了手动维护索引。 - 边界计算使用了
max和min函数,确保了索引不会越界。 - 原地修改避免了额外的存储空间开销。
- 使用
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






