Medium

题目描述

给你一个矩形蛋糕,尺寸为 h x w,以及两个整数数组 horizontalCuts 和 verticalCuts,其中:

  • horizontalCuts[i] 是从矩形蛋糕顶部到第 i 个水平切口的距离
  • verticalCuts[j] 是从矩形蛋糕左侧到第 j 个竖直切口的距离

请你按照数组 horizontalCuts 和 verticalCuts 中给出的水平和竖直位置切割后,请你找出面积最大的那块蛋糕,并返回其面积。由于答案可能是一个很大的数字,因此需要将结果对 10^9 + 7 取余后返回。

示例 1:

输入:h = 5, w = 4, horizontalCuts = [1,2,4], verticalCuts = [1,3]
输出:4 
解释:上图表示了给定的矩形蛋糕。红线表示水平和竖直方向上的切割线。切割蛋糕后,绿色的那块蛋糕具有最大的面积。

示例 2:

输入:h = 5, w = 4, horizontalCuts = [3,1], verticalCuts = [1]
输出:6
解释:上图表示了给定的矩形蛋糕。红线表示水平和竖直方向上的切割线。切割蛋糕后,绿色和黄色的那两块蛋糕具有最大的面积。

示例 3:

输入:h = 5, w = 4, horizontalCuts = [3], verticalCuts = [3]
输出:9

约束条件:

  • 2 <= h, w <= 10^9
  • 1 <= horizontalCuts.length <= min(h - 1, 10^5)
  • 1 <= verticalCuts.length <= min(w - 1, 10^5)
  • 1 <= horizontalCuts[i] < h
  • 1 <= verticalCuts[i] < w
  • horizontalCuts 中的所有元素都是不同的
  • verticalCuts 中的所有元素都是不同的

解题思路

这道题的核心思路是:蛋糕被切割后,最大的矩形块面积等于最大水平间距与最大竖直间距的乘积

解题步骤如下:

  1. 排序切割位置:将水平切割和竖直切割数组分别排序,便于计算相邻切割线之间的距离。

  2. 添加边界:为了计算边界到第一个切割线和最后一个切割线到边界的距离,需要在数组开头添加 0,结尾添加蛋糕的高度/宽度。

  3. 计算最大间距

    • 遍历排序后的水平切割数组,计算相邻两个位置之间的最大距离
    • 遍历排序后的竖直切割数组,计算相邻两个位置之间的最大距离
  4. 计算结果:最大面积 = 最大水平间距 × 最大竖直间距,最后对 10^9 + 7 取余。

时间复杂度主要来自排序操作,空间复杂度为常数级别(不考虑排序的额外空间)。这是一个典型的贪心算法应用,通过找到局部最优解(最大间距)来获得全局最优解。

代码实现

class Solution {
public:
    int maxArea(int h, int w, vector<int>& horizontalCuts, vector<int>& verticalCuts) {
        const int MOD = 1e9 + 7;
        
        // 排序并添加边界
        horizontalCuts.push_back(0);
        horizontalCuts.push_back(h);
        verticalCuts.push_back(0);
        verticalCuts.push_back(w);
        
        sort(horizontalCuts.begin(), horizontalCuts.end());
        sort(verticalCuts.begin(), verticalCuts.end());
        
        // 计算最大水平间距
        int maxH = 0;
        for (int i = 1; i < horizontalCuts.size(); i++) {
            maxH = max(maxH, horizontalCuts[i] - horizontalCuts[i-1]);
        }
        
        // 计算最大竖直间距
        int maxW = 0;
        for (int i = 1; i < verticalCuts.size(); i++) {
            maxW = max(maxW, verticalCuts[i] - verticalCuts[i-1]);
        }
        
        return (1LL * maxH * maxW) % MOD;
    }
};
class Solution:
    def maxArea(self, h: int, w: int, horizontalCuts: List[int], verticalCuts: List[int]) -> int:
        MOD = 10**9 + 7
        
        # 排序并添加边界
        horizontalCuts.extend([0, h])
        verticalCuts.extend([0, w])
        
        horizontalCuts.sort()
        verticalCuts.sort()
        
        # 计算最大水平间距
        max_h = 0
        for i in range(1, len(horizontalCuts)):
            max_h = max(max_h, horizontalCuts[i] - horizontalCuts[i-1])
        
        # 计算最大竖直间距
        max_w = 0
        for i in range(1, len(verticalCuts)):
            max_w = max(max_w, verticalCuts[i] - verticalCuts[i-1])
        
        return (max_h * max_w) % MOD
public class Solution {
    public int MaxArea(int h, int w, int[] horizontalCuts, int[] verticalCuts) {
        const int MOD = 1000000007;
        
        // 添加边界并排序
        var hCuts = new List<int>(horizontalCuts) { 0, h };
        var vCuts = new List<int>(verticalCuts) { 0, w };
        
        hCuts.Sort();
        vCuts.Sort();
        
        // 计算最大水平间距
        int maxH = 0;
        for (int i = 1; i < hCuts.Count; i++) {
            maxH = Math.Max(maxH, hCuts[i] - hCuts[i-1]);
        }
        
        // 计算最大竖直间距
        int maxW = 0;
        for (int i = 1; i < vCuts.Count; i++) {
            maxW = Math.Max(maxW, vCuts[i] - vCuts[i-1]);
        }
        
        return (int)((long)maxH * maxW % MOD);
    }
}
var maxArea = function(h, w, horizontalCuts, verticalCuts) {
    const MOD = 1e9 + 7;
    
    // 排序并添加边界
    horizontalCuts.push(0, h);
    verticalCuts.push(0, w);
    
    horizontalCuts.sort((a, b) => a - b);
    verticalCuts.sort((a, b) => a - b);
    
    // 计算最大水平间距
    let maxH = 0;
    for (let i = 1; i < horizontalCuts.length; i++) {
        maxH = Math.max(maxH, horizontalCuts[i] - horizontalCuts[i-1]);
    }
    
    // 计算最大竖直间距
    let maxW = 0;
    for (let i = 1; i < verticalCuts.length; i++) {
        maxW = Math.max(maxW, verticalCuts[i] - verticalCuts[i-1]);
    }
    
    return (maxH * maxW) % MOD;
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(m log m + n log n)m 为水平切割数量,n 为竖直切割数量,主要时间消耗在排序上
空间复杂度O(1)只使用常数级额外空间(不考虑排序的额外空间)