每日一题·LeetCode2711·对角线上不同值的数量差·Java

题目:

写在前面,看不懂题目直接看我的中译中

给你一个下标从 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) 的左上对角线。类似地,可以定义右下对角线。

示例 1:

输入:grid = [[1,2,3],[3,1,5],[3,2,1]]
输出:[[1,1,0],[1,0,1],[0,1,1]]
解释:第 1 个图表示最初的矩阵 grid 。 
第 2 个图表示对单元格 (0,0) 计算,其中蓝色单元格是位于右下对角线的单元格。
第 3 个图表示对单元格 (1,2) 计算,其中红色单元格是位于左上对角线的单元格。
第 4 个图表示对单元格 (1,1) 计算,其中蓝色单元格是位于右下对角线的单元格,红色单元格是位于左上对角线的单元格。
- 单元格 (0,0) 的右下对角线包含 [1,1] ,而左上对角线包含 [] 。对应答案是 |1 - 0| = 1 。
- 单元格 (1,2) 的右下对角线包含 [] ,而左上对角线包含 [2] 。对应答案是 |0 - 1| = 1 。
- 单元格 (1,1) 的右下对角线包含 [1] ,而左上对角线包含 [1] 。对应答案是 |1 - 1| = 0 。
其他单元格的对应答案也可以按照这样的流程进行计算。

示例 2:

输入:grid = [[1]]
输出:[[0]]
解释:- 单元格 (0,0) 的右下对角线包含 [] ,左上对角线包含 [] 。对应答案是 |0 - 0| = 0 。

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n, grid[i][j] <= 50

 中译中:

给定数组old

求一个新数组new

new数组中的每个数,是old数组中该位置对应的左上角不同数的个数,减去右下角不同值的个数的绝对值

 new[i][j]=(old[i][j]的左上角有几个不同的数-old[i][j]的左上角有几个不同的数)取个绝对值

详解:

  1. 求不同数的个数,容易想到用哈希,直接用hashset,之后取个数就行
  2. 但是这样的时间和空间上的效率都不高
  3. 可以发现,同一条斜线上的数会反复遍历多次,
  4. 为了减少这种情况的发生,
  5. 是否可以计算出每一条向下的斜线
  6. 然后取每一个位置的值的时候,与斜线里的数进行比较,有一样的,和没有一样的输出不一样
  7. 这时,还得考虑到,如何确认当前数所在的位置,因为最后的结果是左上角减右下角,
  8. 所以不能直接一次性计算斜向下的值,而是每进行一步计算一下,也就是前缀和
  9. 这样就要换方式去遍历
  10. 现在难点就在于如何遍历
  11. 至此思路成型开始写代码吧!!!

代码:

原代码:(暴力)

class Solution {
    public int[][] differenceOfDistinctValues(int[][] grid) {
        int m = grid.length;//行
        int n = grid[0].length;//列
        int[][] ans=new int[m][n];//答案数组
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
            HashSet<Integer> num1 =new HashSet<>();
            HashSet<Integer> num2 = new HashSet<>();//放在最里面的for是为了,每次自动刷新,不用手动清除
                int I=i-1,J=j-1;//当前位置向左上遍历
                while(I>=0&&J>=0){
                    num1.add(grid[I][J]);
                    I--;
                    J--;
                }
                I=i+1;//当前位置向右下遍历
                J=j+1;
                while(I<=(m-1)&&J<=(n-1)){
                    num2.add(grid[I][J]);
                    I++;
                    J++;
                }
                ans[i][j]=Math.abs(num1.size()-num2.size());
            }
            
        }
        return ans;
    }
}

改后代码

后续写完查找对角线的题再补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值