【LeetCode 每日一题】2975. 移除栅栏得到的正方形田地的最大面积

Problem: 2975. 移除栅栏得到的正方形田地的最大面积

文章目录

  • 整体思路
      • [1. 核心问题](#1. 核心问题)
      • [2. 算法逻辑](#2. 算法逻辑)
  • 完整代码
  • 时空复杂度
      • [1. 时间复杂度: O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2)](#1. 时间复杂度: O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2))
      • [2. 空间复杂度: O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2)](#2. 空间复杂度: O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2))

整体思路

1. 核心问题

我们需要在一个 m × n m \times n m×n 的矩形田地中,选择水平栅栏(hFences)和垂直栅栏(vFences),构建一个正方形区域。

  • 田地的边界分别是水平线 1m,垂直线 1n
  • 输入给定的 hFencesvFences 是中间的栅栏,边界栅栏默认存在。
  • 目标:找到可能形成的正方形的最大面积。如果无法形成,返回 -1。

2. 算法逻辑

正方形的边长取决于两个栅栏之间的间距

  • 如果在水平方向上存在两个栅栏,它们之间的距离为 L L L。
  • 如果在垂直方向上也存在两个栅栏,它们之间的距离也为 L L L。
  • 那么这两个间距组合起来就能围成一个边长为 L L L 的正方形。

步骤

  1. 预处理栅栏 :对于水平和垂直方向,都要把边界1mn)加入到给定的栅栏数组中。
  2. 计算所有可能的间距
    • 分别计算水平方向所有可能的间距集合 hSet
    • 分别计算垂直方向所有可能的间距集合 vSet
    • 这里使用双重循环遍历排序后的栅栏数组,计算任意两根栅栏之间的距离 fences[j] - fences[i]
  3. 寻找交集最大值
    • 遍历其中一个集合(如 hSet),检查其中的间距是否也存在于另一个集合 vSet 中。
    • 如果是,说明这个长度 L L L 既可以是宽也可以是高,能构成正方形。更新最大边长 ans
  4. 计算结果 :如果找到了合法的正方形(ans > 0),返回面积并取模;否则返回 -1。

完整代码

java 复制代码
import java.util.*;

class Solution {
    final int MOD = 1_000_000_007;

    public int maximizeSquareArea(int m, int n, int[] hFences, int[] vFences) {
        // 1. 获取水平方向所有可能的间距集合
        // m 是水平方向的边界坐标 (行数)
        Set<Integer> hSet = gapSet(hFences, m);
        
        // 2. 获取垂直方向所有可能的间距集合
        // n 是垂直方向的边界坐标 (列数)
        Set<Integer> vSet = gapSet(vFences, n);
        
        // 记录最大合法边长
        int ans = 0;
        
        // 3. 寻找两个集合的交集中的最大值
        // 遍历水平间距集合
        for (int x : hSet) {
            // 如果垂直方向也有相同的间距 x
            if (vSet.contains(x)) {
                // 更新最大边长
                ans = Math.max(ans, x);
            }
        }
        
        // 4. 计算面积并返回
        if (ans == 0) {
            return -1; // 没有找到任何匹配的间距(实际上通常至少有 min(m-1, n-1),除非输入限制特殊)
        }
        
        // 面积可能很大,需要转换成 long 进行乘法,然后取模
        return (int)((long) ans * ans % MOD);
    }

    // 辅助方法:计算所有可能的栅栏间距
    // fences: 内部栅栏坐标数组
    // boundary: 边界坐标 (对应 m 或 n)
    private Set<Integer> gapSet(int[] fences, int boundary) {
        int len = fences.length;
        
        // 创建新数组,长度比原数组多 2,用于存放边界 1 和 boundary
        // fences 本身是引用传递,为了不修改原数组并加入新元素,使用 copyOf
        fences = Arrays.copyOf(fences, len + 2);
        
        // 添加边界栅栏
        fences[len] = 1;
        fences[len + 1] = boundary;
        
        // 排序,方便从小到大计算间距
        Arrays.sort(fences);
        
        // 使用 HashSet 存储所有可能的间距,自动去重
        Set<Integer> st = new HashSet<>();
        
        // 双重循环枚举任意两根栅栏
        for (int i = 0; i < fences.length; i++) {
            for (int j = i + 1; j < fences.length; j++) {
                // 计算间距并加入集合
                st.add(fences[j] - fences[i]);
            }
        }
        return st;
    }
}

时空复杂度

假设 hFences 长度为 H H H,vFences 长度为 V V V。

1. 时间复杂度: O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2)

  • gapSet 函数
    • 排序: O ( H log ⁡ H ) O(H \log H) O(HlogH)。
    • 双重循环枚举所有间距:这是一个组合问题,次数为 C ( H , 2 ) ≈ O ( H 2 ) C(H, 2) \approx O(H^2) C(H,2)≈O(H2)。
    • HashSet 插入操作平均 O ( 1 ) O(1) O(1)。
    • 因此,处理水平栅栏耗时 O ( H 2 ) O(H^2) O(H2),处理垂直栅栏耗时 O ( V 2 ) O(V^2) O(V2)。
  • 交集查找
    • 遍历 hSet,其大小最多为 O ( H 2 ) O(H^2) O(H2)。
    • vSet 中查找,平均 O ( 1 ) O(1) O(1)。
    • 这部分耗时 O ( H 2 ) O(H^2) O(H2)。
  • 总计 : O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2)。
    • 注意:如果 H H H 或 V V V 很大(例如 10 5 10^5 105),这个 O ( N 2 ) O(N^2) O(N2) 算法会超时。但根据题目(LeetCode 2975)的数据约束,栅栏数量通常较小(如 600),允许 O ( N 2 ) O(N^2) O(N2) 通过。

2. 空间复杂度: O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2)

  • 计算依据
    • 我们需要两个 HashSet 来存储所有可能的间距。
    • 水平方向最多有 ( H + 2 ) ( H + 1 ) 2 \frac{(H+2)(H+1)}{2} 2(H+2)(H+1) 个间距,即 O ( H 2 ) O(H^2) O(H2)。
    • 垂直方向最多有 O ( V 2 ) O(V^2) O(V2) 个间距。
  • 结论 : O ( H 2 + V 2 ) O(H^2 + V^2) O(H2+V2)。

参考灵神

相关推荐
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮1 天前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
天疆说1 天前
【哈密顿力学】深入解读航天器交会最优控制中的Hamilton函数
人工智能·算法·机器学习
wuweijianlove1 天前
关于算法设计中的代价函数优化与约束求解的技术7
算法
小程故事多_801 天前
[大模型面试系列] 多轮对话 Agent 设计实战(含窗口优化 + 工具调用精髓)
人工智能·面试·职场和发展
leoufung1 天前
LeetCode 149: Max Points on a Line - 解题思路详解
算法·leetcode·职场和发展
样例过了就是过了1 天前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划
HXDGCL1 天前
矩形环形导轨:自动化循环线的核心运动单元解析
运维·算法·自动化
谭欣辰1 天前
C++ 排列组合完整指南
开发语言·c++·算法
代码中介商1 天前
银行管理系统的业务血肉 —— 流程、状态机、输入校验与持久化(下篇)
c语言·算法