题目描述:
给你一个下标从 0 开始、大小为 m x n 的二维矩阵 grid ,请你求解大小同样为 m x n 的答案矩阵 answer 。
矩阵 answer 中每个单元格 (r, c) 的值可以按下述方式进行计算:
令 topLeft[r][c] 为矩阵 grid 中单元格 (r, c) 左上角对角线上 不同值 的数量。
令 bottomRight[r][c] 为矩阵 grid 中单元格 (r, c) 右下角对角线上 不同值 的数量。
然后 answer[r][c] = |topLeft[r][c] - bottomRight[r][c]| 。
返回矩阵 answer 。
矩阵对角线 是从最顶行或最左列的某个单元格开始,向右下方向走到矩阵末尾的对角线。
如果单元格 (r1, c1) 和单元格 (r, c) 属于同一条对角线且 r1 < r ,则单元格 (r1, c1) 属于单元格 (r, c) 的左上对角线。类似地,可以定义右下对角线。
代码思路:
- 初始化矩阵:先获取矩阵
grid
的行数m
和列数n
,接着初始化一个大小同样为m x n
的答案矩阵ans
,矩阵中所有元素初始值为 0。 - 定义辅助函数:定义一个辅助函数
change
,它有一个参数mode
,用于区分两种不同的对角线遍历方式:mode = 0
:从左下角到右上角遍历对角线。mode = 1
:从右下角到左上角遍历对角线。
- 遍历对角线:在
change
函数里,依据mode
的值确定遍历的起始位置,然后用两个字典top
和bottom
分别记录左上角和右下角对角线上不同值的数量。 - 计算差值:遍历对角线时,更新
top
和bottom
字典,同时计算每个单元格的左上角和右下角对角线上不同值的数量的差值的绝对值,将其存入答案矩阵ans
中。 - 返回结果:调用
change
函数两次,分别处理两种不同的对角线遍历方式,最后返回答案矩阵ans
。
代码实现:
from collections import defaultdict
from typing import List
class Solution:
def differenceOfDistinctValues(self, grid: List[List[int]]) -> List[List[int]]:
# 获取矩阵的行数和列数
m, n = len(grid), len(grid[0])
# 初始化答案矩阵,所有元素初始值为 0
ans = [[0] * n for _ in range(m)]
def change(mode=0): # mode=0,左下-右下;mode=1,后下-右上
# 根据 mode 的值确定遍历的起始位置
LOOP = range(n) if mode == 0 else range(m-2, -1, -1)
for j in LOOP:
# 初始化两个字典,用于记录左上角和右下角对角线上不同值的数量
top = defaultdict(int)
bottom = defaultdict(int)
# 根据 mode 的值确定起始位置
if mode == 0:
r, s = m-1, j
else:
r, s = j, n-1
# 遍历左上角对角线,统计不同值的数量
while r >= 0 and s >= 0:
top[grid[r][s]] += 1
r -= 1
s -= 1
# 重置起始位置
if mode == 0:
r, s = m-1, j
else:
r, s = j, n-1
# 遍历对角线,更新 top 和 bottom 字典,计算差值并更新答案矩阵
while r >= 0 and s >= 0:
d = grid[r][s]
top[d] -= 1
if top[d] == 0:
del top[d]
ans[r][s] = abs(len(top)-len(bottom))
bottom[d] += 1
r -= 1
s -= 1
# 处理左下角到右上角的对角线
change(0)
# 处理右下角到左上角的对角线
change(1)
return ans