[特殊字符] LeetCode 做题笔记(一):1878. 矩阵中最大的三个菱形和

📝 LeetCode 做题笔记(一):1878. 矩阵中最大的三个菱形和

题目链接1878. 矩阵中最大的三个菱形和
难度 :中等 | 语言 :Java | 标签:数组、数学、矩阵、前缀和、枚举


🔍 题目理解

给定一个 m x n 的整数矩阵 grid菱形和 指的是菱形边界上的元素之和。菱形定义为正方形旋转45度,四个角必须落在格子上,且可以为"面积为0"的单点菱形。

要求:返回矩阵中 三个最大的、互不相同的 菱形和,按降序排列。

📌 关键要点

  1. 只计算菱形的边界,不包含内部
  2. 菱形边长可以为0(即单个点)
  3. 结果要去重,不足3个时返回全部

💡 解题思路:暴力枚举 + TreeSet维护

核心思想

数据范围较小(m, n ≤ 100),可以直接枚举所有可能的菱形

步骤拆解:

1️⃣ 枚举菱形中心 + 半径

  • 遍历每个格子 (i, j) 作为菱形的中心点

  • 枚举菱形的"半径" k(从0开始,表示边长)

  • 对于半径为 k 的菱形,四个顶点坐标为:

    复制代码
    上: (i-k, j)     下: (i+k, j)
    左: (i, j-k)     右: (i, j+k)

2️⃣ 边界合法性检查

java 复制代码
// 确保四个顶点都在矩阵范围内
if (i - k < 0 || i + k >= m || j - k < 0 || j + k >= n) {
    break;  // 更大半径肯定也越界
}

3️⃣ 计算菱形边界和

  • 半径为0:直接取 grid[i][j]
  • 半径>0:沿四条边累加(注意四个顶点只算一次)

4️⃣ 维护前三大不重复值

  • 使用 TreeSet 自动去重 + 排序,保持大小不超过3

🧩 代码实现(Java)

java 复制代码
class Solution {
    public int[] getBiggestThree(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        // TreeSet自动去重+升序排列,我们最后反转即可
        TreeSet<Integer> results = new TreeSet<>();
        
        // 枚举每个点作为菱形中心
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 半径为0的菱形(单点)
                results.add(grid[i][j]);
                // 保持最多3个元素
                if (results.size() > 3) {
                    results.pollFirst();  // 移除最小值
                }
                
                // 枚举更大半径
                int k = 1;
                while (i - k >= 0 && i + k < m && j - k >= 0 && j + k < n) {
                    // 计算菱形边界和
                    int sum = 0;
                    
                    // 上→右:从 (i-k, j) 到 (i, j+k)
                    for (int step = 0; step < k; step++) {
                        sum += grid[i - k + step][j + step];
                    }
                    // 右→下:从 (i, j+k) 到 (i+k, j)
                    for (int step = 0; step < k; step++) {
                        sum += grid[i + step][j + k - step];
                    }
                    // 下→左:从 (i+k, j) 到 (i, j-k)
                    for (int step = 0; step < k; step++) {
                        sum += grid[i + k - step][j - step];
                    }
                    // 左→上:从 (i, j-k) 到 (i-k, j)
                    for (int step = 0; step < k; step++) {
                        sum += grid[i - step][j - k + step];
                    }
                    
                    results.add(sum);
                    if (results.size() > 3) {
                        results.pollFirst();
                    }
                    
                    k++;
                }
            }
        }
        
        // 转为降序数组返回
        int[] ans = new int[results.size()];
        int idx = ans.length - 1;
        for (int num : results) {
            ans[idx--] = num;
        }
        return ans;
    }
}

⚡ 优化技巧:前缀和加速(可选)

如果追求极致性能,可预处理对角线前缀和

java 复制代码
// 预处理两条对角线方向的前缀和
// diag1: 左上→右下,diag2: 右上→左下
int[][] diag1 = new int[m + 1][n + 1];
int[][] diag2 = new int[m + 1][n + 1];

for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
        diag1[i + 1][j + 1] = grid[i][j] + diag1[i][j];
        diag2[i + 1][j] = grid[i][j] + diag2[i][j + 1];
    }
}

这样计算任意对角线段和可做到 O(1),整体复杂度从 O(mnk²) 降至 O(mnk)。


📊 复杂度分析

方法 时间复杂度 空间复杂度
暴力枚举 O(m·n·min(m,n)²) O(1)(不计结果集)
+前缀和优化 O(m·n·min(m,n)) O(m·n)

💡 实际测试中,由于数据范围小,暴力法已足够通过


🎯 总结 & 易错点

收获

  • 几何枚举题的坐标变换技巧
  • Java中 TreeSet 的使用:pollFirst() 移除最小值,迭代器默认升序
  • "边界和"与"区域和"的区别

易错点

  1. 菱形顶点重复计算(每条边累加时注意端点)
  2. 半径枚举的边界条件(while 而非 for 更易控制)
  3. 结果去重 + 降序输出的细节(TreeSet转数组时注意顺序)
相关推荐
a1117761 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
破碎的南瓜2 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
你想知道什么?3 小时前
线性回归-学习笔记
笔记·学习·线性回归
谙弆悕博士3 小时前
系统集成项目管理工程师教程(第3版)笔记——第17章:法律法规和标准规范
笔记·职场和发展·学习方法·业界资讯·软考·法律·法规
谙弆悕博士5 小时前
系统集成项目管理工程师教程(第3版)笔记——第4章:信息系统架构
笔记·系统架构·项目管理·创业创新·学习方法·业界资讯·物理
茯苓gao6 小时前
嵌入式开发笔记:Qt信号槽机制深度解析——从原理到实战的全方位指南
开发语言·笔记·嵌入式硬件·qt·学习
Xzaveir_7777 小时前
OPPO、vivo、荣耀号码认证:多终端拨测矩阵与异常复现
大数据·网络·科技·矩阵·产品经理·ai-native
A.零点8 小时前
【期末复习,408 考研计组全程笔记 】— 第4章 :指令系统
笔记·考研·408·计算机组成原理
早茶cc8 小时前
sqli1-5 9报错注入 笔记
笔记
摇滚侠8 小时前
Java 全栈开发实战教程 课程笔记 34-36
java·笔记