[特殊字符] 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转数组时注意顺序)
相关推荐
一条破秋裤9 分钟前
STM32 学习笔记:中断系统与 EXTI 外部中断
笔记·stm32·学习
摇滚侠13 分钟前
《SpringBoot 3:入门与应用实战》第 9 章 使用 WebMvc 开发应用 阅读笔记 21
java·spring boot·笔记
xieliyu.27 分钟前
计算机网络‑IP 协议解析:核心特性总结
网络·笔记·网络协议·学习·tcp/ip·计算机网络
陈年老古董32 分钟前
PyTorch 实现 MNIST 手写数字识别学习笔记
笔记·python·深度学习·学习
远航计算机35 分钟前
豆包”精采信”模式对企业官网运营有什么影响?2026年7月信源重构深度解读
人工智能·矩阵·重构·aigc·媒体
风123456789~37 分钟前
【架构设计】3.2 信息化系统的典型应用 3/6
笔记·系统架构设计
旖旎夜光1 小时前
LeetCode 238:除自身以外数组的乘积(前缀和) —— 题解
数据结构·c++·算法·leetcode·前缀和
风123456789~1 小时前
【架构设计】第3章 信息系统基础知识 1/6
笔记·系统架构设计
吃着火锅x唱着歌1 小时前
Effective C++ 学习笔记 条款45 运用成员函数模板接受所有兼容类型
c++·笔记·学习
Capricorn19881 小时前
Ox Alpha 1M 上下文科研引用失真怎么排查?知芽 Notebook Skill 技术链路实操
人工智能·笔记·python·深度学习·知识图谱·论文笔记