对角线上不同值的数量差-LeetCode
2711. 对角线上不同值的数量差
🎯 问题描述
描述:
给你一个下标从 0 开始的 m x n 二维整数数组 grid。
你需要返回一个同样大小的矩阵 answer,其中 answer[i][j] 的值为:
其中:
topLeft[i][j]表示单元格(i, j)左上角对角线(即行下标和列下标都小于i和j的方向)上不同值的数量。bottomRight[i][j]表示单元格(i, j)右下角对角线(即行下标和列下标都大于i和j的方向)上不同值的数量。- 如果对角线上没有元素,则数量为 0。
说明:
-
这是一个矩阵对角线遍历问题。
-
核心策略:
- 同一条主对角线(左上到右下)上的元素,其坐标差
i - j是恒定的。 - 我们可以根据
i - j的值将矩阵元素分组到不同的对角线上。 - 对于每一条对角线,我们需要计算每个位置左侧(左上)的不同值数量和右侧(右下)的不同值数量。
- 同一条主对角线(左上到右下)上的元素,其坐标差
-
优化技巧:
- 两次遍历法:先沿对角线从左上往右下遍历,计算并暂存
topLeft值;再沿同一条对角线从右下往左上遍历,计算bottomRight值,并直接计算最终差值。 - 空间复用:利用结果矩阵
ans暂存中间状态(topLeft),避免开辟额外数组。
- 两次遍历法:先沿对角线从左上往右下遍历,计算并暂存
-
示例:
-
示例 1:
1 | 输入:grid = [[1,2,3],[3,1,2]] |
💻 解题思路
思路1:对角线分组 + 双向集合计数
核心逻辑
- 对角线标识:
- 主对角线方向(左上到右下)的特征是
i - j = C(常数)。 - 代码中使用
k作为枚举变量,通过i = k + j - n变换,实际上是在遍历所有可能的i - j值。 k的范围1到m + n - 1覆盖了所有可能的对角线。
- 主对角线方向(左上到右下)的特征是
- 确定边界:
- 对于每条对角线,计算其在矩阵内的有效列下标范围
[min_j, max_j]。 min_j = max(0, n - k)和max_j = min(n - 1, m - 1 + n - k)确保了i和j都不越界。
- 对于每条对角线,计算其在矩阵内的有效列下标范围
- 正向遍历(计算 topLeft):
- 沿对角线从左上(
j小)到右下(j大)。 - 使用集合
st记录当前点之前遇到的不同值。 ans[i][j] = len(st):此时集合大小即为左上角不同值数量。st.add(grid[i][j]):将当前值加入集合,供下一个点使用。
- 沿对角线从左上(
- 反向遍历(计算 bottomRight 并得出结果):
- 沿同一条对角线从右下(
j大)到左上(j小)。 - 清空集合
st。 - 使用集合
st记录当前点之后(右下方)遇到的不同值。 ans[i][j] = abs(ans[i][j] - len(st)):ans[i][j]中存的是刚才计算的topLeft。len(st)是当前的bottomRight。- 直接计算差值并更新
ans[i][j]。
st.add(grid[i][j]):将当前值加入集合,供下一个点(左上方的点)使用。
- 沿同一条对角线从右下(
代码实现
1 | class Solution: |
📊 性能分析
- 时间复杂度:
- 我们遍历了矩阵中的每一条对角线。
- 每个元素被访问两次(一次正向,一次逆向)。
- 集合操作(添加、查询大小)的平均时间复杂度为 。
- 总时间复杂度与矩阵元素数量成线性关系。
- 空间复杂度:
- 结果矩阵
ans占用 。 - 集合
st用于存储不同值,其最大大小受限于对角线的最大长度,即 。 - 注:如果不计算结果矩阵的空间,额外空间复杂度仅为 。
- 结果矩阵
思考
-
为什么可以复用
ans数组?- 在正向遍历时,我们需要存储
topLeft的值。 - 在逆向遍历时,我们需要
topLeft和bottomRight来计算结果。 - 此时
topLeft已经计算完毕且不再改变,而bottomRight是即时计算的。 - 因此,我们可以先用
ans存topLeft,然后在逆向遍历时直接覆盖为最终结果。这是一种非常节省空间的技巧。
- 在正向遍历时,我们需要存储
-
坐标变换公式
i = k + j - n:- 这个公式定义了当前枚举的对角线。
- 实际上,这对应于
i - j = k - n。 - 令 ,则
i - j = C。这正是主对角线方向(左上到右下)的特征方程。 - 通过改变
k,我们遍历了所有可能的 值,从而覆盖了整个矩阵。
-
集合
st的作用:- 集合用于去重。
- 正向遍历时,
st保存了当前点之前(左上方)遇到的所有不同值。 - 逆向遍历时,
st保存了当前点之后(右下方)遇到的所有不同值。
-
边界计算:
min_j和max_j的计算确保了我们在遍历对角线时不会越界访问矩阵。- 这是通过对
i和j的范围限制推导出来的。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






