题目

2711. 对角线上不同值的数量差

给你一个下标从 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

思路

​ 先读懂题目,这里的矩阵对角线仅仅是指,左上方到右下角这个方向的对角线。如果当前位置坐标是(i, j),左上对角线是指 (i-1, j-1)、(i-2, j-2)、 (i-3, j-3)、... 这些位置的连线,右下对焦线只是 (i+1, j+1)、(i+2, j+2)、(i+3, j+3)、... 这些位置的连线。左上对角线和右上对角线都不包含当前节点。

​ 读懂题意后,可以直接模拟,遍历二维数组的每个位置,然后求出这个位置左上角和右下角对角线中不同数值的数量。这里不同值最直观的方法是直接用Set去重。不过注意到值范围[1, 50]很小,我们可以用bitmap的思路,用一个Long类型(64位)的值来存,如果某个值 x 出现,就把从右开始第x位置为1,那么最后不同值的数量就是这个Long值的二进制表示中,1的数量。

图解

代码

优化

​ 上述直接模拟的方法中,对于同一条对角线,遍历到对角线上每一个位置的时候,都被计算了一遍,存在浪费。我们在遍历二维数组的时候,可以不按照传统的行和列来遍历,而是按照对角线来遍历。对于同一条对角线的位置,我们不难发现 i - j 的值都是相等的,所以我们可以使用 i-j 来记录1条对角线。这条对角线的位置就形成了1个1维数组,我们只需要从前往后、从后往前各遍历1次,就可以得到每个位置左上和右下部分不同值的数量了。

优化后代码

public int[][] differenceOfDistinctValues(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] ans = new int[m][n];
// 记录左上方对角线出现的数值
long leftTop = 0L;
// 记录右下方对角线出现的数值
long rightBottom = 0L;
// 对于每1条对角线,使用 i - j 来表示,对角线上的每个数字,i - j 的值是相同的
for (int k = 1 - n; k <= m - 1; k++) {
// 计算左上角出现的数值
leftTop = 0;
// 对于每个k值,要同时满足 0 <= i < m && 0 <= j < n
for (int i = 0 ; i < m; i++) {
int j = i - k;
// 排除掉越界的情况
if (j < 0 || j >= n) {
continue;
}
ans[i][j] = Long.bitCount(leftTop);
leftTop |= 1L << grid[i][j];
} // 计算右下角出现的数值
rightBottom = 0L;
for (int i = m-1 ; i >= 0; i--) {
int j = i - k;
// 排除掉越界的情况
if (j < 0 || j >= n) {
continue;
}
ans[i][j] = Math.abs(ans[i][j] - Long.bitCount(rightBottom));
rightBottom |= 1L << grid[i][j];
}
}
return ans;
}

耗时

leetcode每日一题:对角线上不同值的数量差的更多相关文章

  1. 【python】Leetcode每日一题-逆波兰表达式求值

    [python]Leetcode每日一题-逆波兰表达式求值 [题目描述] 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说 ...

  2. 【JavaScript】Leetcode每日一题-在D天内送包裹的能力

    [JavaScript]Leetcode每日一题-在D天内送包裹的能力 [题目描述] 传送带上的包裹必须在 D 天内从一个港口运送到另一个港口. 传送带上的第 i 个包裹的重量为 weights[i] ...

  3. 【JavaScript】Leetcode每日一题-青蛙过河

    [JavaScript]Leetcode每日一题-青蛙过河 [题目描述] 一只青蛙想要过河. 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有). 青蛙可以跳上石子 ...

  4. 【JavaScript】Leetcode每日一题-矩形区域不超过K的最大值和

    [JavaScript]Leetcode每日一题-矩形区域不超过K的最大值和 [题目描述] 给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大 ...

  5. 【JavaScript】【KMP】Leetcode每日一题-实现strStr()

    [JavaScript]Leetcode每日一题-实现strStr() [题目描述] 实现 strStr() 函数. 给你两个字符串 haystack 和 needle ,请你在 haystack 字 ...

  6. [LeetCode每日一题]153.寻找旋转排序数组中的最小值

    [LeetCode每日一题]153.寻找旋转排序数组中的最小值 问题 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组 nums = [0,1, ...

  7. [LeetCode每日一题]81. 搜索旋转排序数组 II

    [LeetCode每日一题]81. 搜索旋转排序数组 II 问题 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 & ...

  8. 【python】Leetcode每日一题-存在重复元素3

    [python]Leetcode每日一题-存在重复元素3 [题目描述] 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] ...

  9. 【python】Leetcode每日一题-搜索排序数组2

    [python]Leetcode每日一题-搜索排序数组2 [题目描述] 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k( ...

  10. [LeetCode每日一题]1143. 最长公共子序列

    [LeetCode每日一题]1143. 最长公共子序列 问题 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . 一个字符串 ...

随机推荐

  1. SpringCloud Alibaba(四) - Nacos 配置中心

    1.环境搭建 1.1 依赖 <!-- nacos注册中心 注解 @EnableDiscoveryClient --> <dependency> <groupId>c ...

  2. postman环境设置以及参数传递

    通常一个公司项目有不同的环境(开发环境,测试环境,上线环境),在做测试时候,有可能会遇到接口改变之类的,postman保存了很多接口,想要再测试局需要多次修改域名或者端口,这个时候就需要配置环境 1. ...

  3. Forrester Wave™报告:天翼云三项产品能力获评最高分!

    8月5日,国际权威研究机构Forrester发布了<Forrester Wave: 中国公有云平台厂商评测,2024Q3>报告.中国电信天翼云凭借前瞻性的发展战略和领先的产品能力,跻身行业 ...

  4. [OI 向] 深入理解二阶线性递推

    本文主要面向普及/提高组 OIer 和 ACMer.考虑大多数 OIer 的情况,本文默认读者只会矩阵乘法,不了解矩阵的行列式,矩阵的秩等内容.本文使用 C++ 编写代码示例. 什么是二阶线性递推 二 ...

  5. 流程控制之Scanner

    Scanner对象 可以通过scanner类(java.util.Scanner)来获取用户的输入 基本语法: Scanner s = new Scanner(System.in); 通过Scanne ...

  6. 深度科普 - 大名鼎鼎的bun.js到底是什么? 它能否替代node.js? 是否能成为前端生态的未来?

    什么是bun? 聪明的小伙伴们,你们在接触bun时是否有过这样的疑问呢? bun.js是什么? 它是如何诞生的? 跟node.js的区别是什么? 有什么优势? 目前的发展情况如何了? 他是否是前端的未 ...

  7. ARC165F题解

    前言 \(2024.10.19\) 日校测 \(T4\),思维太庙,被薄纱了,遂哭弱,写题解以记之. 简要题意 给你一个长度为 \(2n\) 的序列满足 \(\forall a_i\in[1,n]\) ...

  8. 5. Nginx 负载均衡配置案例(附有详细截图说明++)

    5. Nginx 负载均衡配置案例(附有详细截图说明++) @ 目录 5. Nginx 负载均衡配置案例(附有详细截图说明++) 1. Nginx 负载均衡 配置实例 3. 注意事项和避免的坑 4. ...

  9. 在 Aspire 项目下使用 AgileConfig

    什么是 Aspire .NET Aspire 是一组工具.模板和包,用于构建易于监控的.可投入生产的应用程序..NET Aspire 通过一系列 NuGet 包交付,这些包通过启动或解决现代应用开发中 ...

  10. tinyint、int的区别

    1.tinyint(1字节--4位[带符号]) 很小的整数.带符号的范围是-128到127.无符号的范围是0到255. 2.smallint(2字节--6位[带符号]) 小的整数.带符号的范围是-32 ...