1465. Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts
Problem Description
You have a rectangular cake with dimensions h
(height) ร w
(width). You need to make cuts on this cake using two sets of cutting positions:
horizontalCuts[i]
represents the distance from the top edge where you make thei
-th horizontal cutverticalCuts[j]
represents the distance from the left edge where you make thej
-th vertical cut
After making all the cuts specified in both arrays, the cake will be divided into multiple rectangular pieces. Your task is to find the maximum area among all these pieces.
For example, if you have a cake of size 5ร4 and make horizontal cuts at distances 1 and 3 from the top, and vertical cuts at distances 1 and 3 from the left, you'll create several rectangular pieces. The pieces will have various sizes based on the distances between consecutive cuts (including the edges of the original cake).
The key insight is that the area of any piece is determined by the product of:
- The distance between two consecutive horizontal cuts (or between a cut and an edge)
- The distance between two consecutive vertical cuts (or between a cut and an edge)
To find the maximum area, you need to find the maximum gap between consecutive horizontal positions and the maximum gap between consecutive vertical positions, then multiply these two values.
Since the result can be very large, return the answer modulo 10^9 + 7
.
Intuition
When we make cuts on the cake, we're essentially creating grid lines. Each piece of cake is bounded by two consecutive horizontal lines and two consecutive vertical lines. The area of each piece equals the height difference between its horizontal boundaries multiplied by the width difference between its vertical boundaries.
The key observation is that we can think about this problem independently in two dimensions. For the horizontal dimension, we need to find all the gaps between consecutive cuts (including the edges at 0 and h). Similarly for the vertical dimension with gaps between cuts (including edges at 0 and w).
Since any piece is formed by choosing one horizontal gap and one vertical gap, and we want the maximum area, we should choose the largest horizontal gap and multiply it by the largest vertical gap. This works because:
- Every piece must use exactly one horizontal gap and one vertical gap
- The gaps are independent of each other
- To maximize the product of two positive numbers, we should choose the largest available values
For example, if the maximum horizontal gap is 3 units and the maximum vertical gap is 4 units, then the largest possible piece will have area 3 ร 4 = 12
.
To find these maximum gaps efficiently, we sort both arrays of cuts, add the boundary positions (0 and h for horizontal, 0 and w for vertical), and then iterate through consecutive pairs to find the maximum difference. The sorting ensures that we can easily find the distance between consecutive cuts by simple subtraction.
The modulo operation 10^9 + 7
is applied at the end to handle potential overflow issues with large numbers.
Solution Approach
The implementation follows these steps:
-
Add boundary positions: First, we extend both
horizontalCuts
andverticalCuts
arrays by adding the boundary positions. For horizontal cuts, we add0
(top edge) andh
(bottom edge). For vertical cuts, we add0
(left edge) andw
(right edge). This ensures we consider the gaps between cuts and the cake edges. -
Sort the arrays: We sort both
horizontalCuts
andverticalCuts
in ascending order. After sorting, consecutive elements in the array represent adjacent cutting positions or edges. -
Find maximum gaps:
- For horizontal cuts, we iterate through consecutive pairs using
pairwise(horizontalCuts)
and calculate the differenceb - a
for each pair(a, b)
. We keep track of the maximum difference asx
. - Similarly for vertical cuts, we find the maximum difference between consecutive positions and store it as
y
.
- For horizontal cuts, we iterate through consecutive pairs using
-
Calculate the result: The maximum area is simply the product of the maximum horizontal gap
x
and the maximum vertical gapy
. We apply modulo10^9 + 7
to the final result to prevent overflow.
The pairwise
function is a Python utility that creates pairs of consecutive elements from an iterable. For example, pairwise([1, 3, 5, 8])
yields (1, 3)
, (3, 5)
, (5, 8)
.
Time Complexity: O(n log n + m log m)
where n
is the length of horizontalCuts
and m
is the length of verticalCuts
, due to the sorting operations.
Space Complexity: O(1)
if we don't count the space used for sorting, or O(n + m)
if we do.
The beauty of this solution is its simplicity - by recognizing that horizontal and vertical dimensions are independent, we can solve each dimension separately and combine the results with a simple multiplication.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach.
Example: We have a cake with height h = 5
and width w = 4
. We make:
- Horizontal cuts at positions
[1, 2, 4]
(distances from top) - Vertical cuts at position
[3]
(distance from left)
Step 1: Add boundary positions
- Horizontal positions become:
[0, 1, 2, 4, 5]
(added 0 for top edge and 5 for bottom edge) - Vertical positions become:
[0, 3, 4]
(added 0 for left edge and 4 for right edge)
Step 2: Sort the arrays In this case, after adding boundaries:
- Horizontal:
[0, 1, 2, 4, 5]
(already sorted) - Vertical:
[0, 3, 4]
(already sorted)
Step 3: Find maximum gaps
For horizontal gaps (between consecutive positions):
- Gap between 0 and 1:
1 - 0 = 1
- Gap between 1 and 2:
2 - 1 = 1
- Gap between 2 and 4:
4 - 2 = 2
- Gap between 4 and 5:
5 - 4 = 1
- Maximum horizontal gap
x = 2
For vertical gaps:
- Gap between 0 and 3:
3 - 0 = 3
- Gap between 3 and 4:
4 - 3 = 1
- Maximum vertical gap
y = 3
Step 4: Calculate the result
Maximum area = x ร y = 2 ร 3 = 6
This represents a piece that spans 2 units vertically (from position 2 to position 4) and 3 units horizontally (from position 0 to position 3). The final answer would be 6 % (10^9 + 7) = 6
.
The cake is divided into 8 pieces total, with areas: 3, 1, 3, 1, 6, 2, 3, 1. The maximum among these is indeed 6.
Solution Implementation
1class Solution:
2 def maxArea(
3 self, h: int, w: int, horizontalCuts: List[int], verticalCuts: List[int]
4 ) -> int:
5 # Add boundaries (0 and max values) to both cut lists
6 horizontalCuts.extend([0, h])
7 verticalCuts.extend([0, w])
8
9 # Sort both lists to process consecutive cuts
10 horizontalCuts.sort()
11 verticalCuts.sort()
12
13 # Find maximum gap between consecutive horizontal cuts
14 max_height = 0
15 for i in range(1, len(horizontalCuts)):
16 max_height = max(max_height, horizontalCuts[i] - horizontalCuts[i - 1])
17
18 # Find maximum gap between consecutive vertical cuts
19 max_width = 0
20 for i in range(1, len(verticalCuts)):
21 max_width = max(max_width, verticalCuts[i] - verticalCuts[i - 1])
22
23 # Return the area of the largest piece modulo 10^9 + 7
24 MOD = 10**9 + 7
25 return (max_height * max_width) % MOD
26
1class Solution {
2 public int maxArea(int h, int w, int[] horizontalCuts, int[] verticalCuts) {
3 // Define modulo constant for result overflow prevention
4 final int MOD = (int) 1e9 + 7;
5
6 // Sort both cut arrays to process consecutive cuts
7 Arrays.sort(horizontalCuts);
8 Arrays.sort(verticalCuts);
9
10 // Get the lengths of both cut arrays
11 int horizontalCutsCount = horizontalCuts.length;
12 int verticalCutsCount = verticalCuts.length;
13
14 // Initialize max horizontal distance considering edges
15 // Check distance from top edge to first cut and from last cut to bottom edge
16 long maxHorizontalDistance = Math.max(
17 horizontalCuts[0], // Distance from top edge (0) to first cut
18 h - horizontalCuts[horizontalCutsCount - 1] // Distance from last cut to bottom edge
19 );
20
21 // Initialize max vertical distance considering edges
22 // Check distance from left edge to first cut and from last cut to right edge
23 long maxVerticalDistance = Math.max(
24 verticalCuts[0], // Distance from left edge (0) to first cut
25 w - verticalCuts[verticalCutsCount - 1] // Distance from last cut to right edge
26 );
27
28 // Find maximum horizontal distance between consecutive cuts
29 for (int i = 1; i < horizontalCutsCount; i++) {
30 long currentDistance = horizontalCuts[i] - horizontalCuts[i - 1];
31 maxHorizontalDistance = Math.max(maxHorizontalDistance, currentDistance);
32 }
33
34 // Find maximum vertical distance between consecutive cuts
35 for (int i = 1; i < verticalCutsCount; i++) {
36 long currentDistance = verticalCuts[i] - verticalCuts[i - 1];
37 maxVerticalDistance = Math.max(maxVerticalDistance, currentDistance);
38 }
39
40 // Calculate the maximum area and apply modulo
41 // Maximum area = maximum horizontal distance ร maximum vertical distance
42 return (int) ((maxHorizontalDistance * maxVerticalDistance) % MOD);
43 }
44}
45
1class Solution {
2public:
3 int maxArea(int h, int w, vector<int>& horizontalCuts, vector<int>& verticalCuts) {
4 // Add boundaries (top/bottom for horizontal, left/right for vertical)
5 horizontalCuts.push_back(0);
6 horizontalCuts.push_back(h);
7 verticalCuts.push_back(0);
8 verticalCuts.push_back(w);
9
10 // Sort both arrays to process cuts in order
11 sort(horizontalCuts.begin(), horizontalCuts.end());
12 sort(verticalCuts.begin(), verticalCuts.end());
13
14 // Find maximum gap between consecutive horizontal cuts
15 int maxHorizontalGap = 0;
16 for (int i = 1; i < horizontalCuts.size(); ++i) {
17 maxHorizontalGap = max(maxHorizontalGap, horizontalCuts[i] - horizontalCuts[i - 1]);
18 }
19
20 // Find maximum gap between consecutive vertical cuts
21 int maxVerticalGap = 0;
22 for (int i = 1; i < verticalCuts.size(); ++i) {
23 maxVerticalGap = max(maxVerticalGap, verticalCuts[i] - verticalCuts[i - 1]);
24 }
25
26 // Calculate the area of the largest piece (max horizontal gap * max vertical gap)
27 // Use 1LL to ensure 64-bit multiplication before taking modulo
28 const int MOD = 1e9 + 7;
29 return (1LL * maxHorizontalGap * maxVerticalGap) % MOD;
30 }
31};
32
1/**
2 * Finds the maximum area of a rectangle piece after cutting a rectangular cake
3 * @param h - Height of the rectangular cake
4 * @param w - Width of the rectangular cake
5 * @param horizontalCuts - Array of positions where horizontal cuts are made
6 * @param verticalCuts - Array of positions where vertical cuts are made
7 * @returns Maximum area of a rectangle piece modulo 10^9 + 7
8 */
9function maxArea(h: number, w: number, horizontalCuts: number[], verticalCuts: number[]): number {
10 // Define modulo constant for large number handling
11 const MODULO: number = 1e9 + 7;
12
13 // Add boundaries (0 and max values) to both cut arrays
14 horizontalCuts.push(0, h);
15 verticalCuts.push(0, w);
16
17 // Sort both arrays in ascending order to calculate consecutive differences
18 horizontalCuts.sort((a: number, b: number) => a - b);
19 verticalCuts.sort((a: number, b: number) => a - b);
20
21 // Initialize variables to track maximum distances
22 let maxHorizontalGap: number = 0;
23 let maxVerticalGap: number = 0;
24
25 // Find the maximum gap between consecutive horizontal cuts
26 for (let i: number = 1; i < horizontalCuts.length; i++) {
27 const currentGap: number = horizontalCuts[i] - horizontalCuts[i - 1];
28 maxHorizontalGap = Math.max(maxHorizontalGap, currentGap);
29 }
30
31 // Find the maximum gap between consecutive vertical cuts
32 for (let i: number = 1; i < verticalCuts.length; i++) {
33 const currentGap: number = verticalCuts[i] - verticalCuts[i - 1];
34 maxVerticalGap = Math.max(maxVerticalGap, currentGap);
35 }
36
37 // Calculate the maximum area using BigInt to handle potential overflow
38 // Then apply modulo operation and convert back to number
39 const maxArea: bigint = (BigInt(maxHorizontalGap) * BigInt(maxVerticalGap)) % BigInt(MODULO);
40 return Number(maxArea);
41}
42
Time and Space Complexity
The time complexity is O(m log m + n log n)
, where m
and n
are the lengths of horizontalCuts
and verticalCuts
, respectively. This is because:
- The
extend()
operations add constant elements to each list inO(1)
time - The
sort()
operation onhorizontalCuts
(now withm+2
elements) takesO((m+2) log(m+2)) = O(m log m)
time - The
sort()
operation onverticalCuts
(now withn+2
elements) takesO((n+2) log(n+2)) = O(n log n)
time - The
pairwise()
iterations and max operations takeO(m)
andO(n)
time respectively, which are dominated by the sorting operations
The space complexity is O(log m + log n)
. This comes from:
- The sorting algorithms (typically Timsort in Python) use
O(log m)
andO(log n)
space for the recursion stack - The
pairwise()
function creates an iterator that usesO(1)
additional space - The
extend()
operations modify the lists in-place, though they do increase the list sizes by constant amounts
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Modifying Input Arrays In-Place
The code uses extend()
to add boundaries to the input arrays, which modifies them directly. This can cause issues if the same arrays are used elsewhere or if the function is called multiple times with the same inputs.
Problem Example:
h_cuts = [1, 3] v_cuts = [1, 3] solution = Solution() result1 = solution.maxArea(5, 4, h_cuts, v_cuts) # h_cuts is now [1, 3, 0, 5] - modified! result2 = solution.maxArea(5, 4, h_cuts, v_cuts) # Wrong result because h_cuts already contains boundaries
Solution: Create copies of the arrays or use list concatenation:
horizontalCuts = sorted(horizontalCuts + [0, h])
verticalCuts = sorted(verticalCuts + [0, w])
2. Integer Overflow in Other Languages
While Python handles large integers automatically, in languages like Java or C++, computing max_height * max_width
directly might cause integer overflow before applying modulo.
Solution for other languages: Apply modulo during multiplication or use long/64-bit integers:
# For languages with overflow concerns: return ((max_height % MOD) * (max_width % MOD)) % MOD
3. Forgetting Edge Cases
Not handling empty cut arrays properly. While the problem likely guarantees non-empty arrays, defensive programming suggests checking.
Solution:
if not horizontalCuts: horizontalCuts = [] if not verticalCuts: verticalCuts = []
4. Using pairwise() Incorrectly
The explanation mentions pairwise()
but the actual code uses manual indexing. If using pairwise()
(Python 3.10+), ensure proper import:
from itertools import pairwise
# Then use:
max_height = max(b - a for a, b in pairwise(horizontalCuts))
max_width = max(b - a for a, b in pairwise(verticalCuts))
Corrected Complete Solution:
class Solution:
def maxArea(self, h: int, w: int, horizontalCuts: List[int], verticalCuts: List[int]) -> int:
# Create new sorted lists with boundaries
horizontalCuts = sorted(horizontalCuts + [0, h])
verticalCuts = sorted(verticalCuts + [0, w])
# Find maximum gaps
max_height = max(horizontalCuts[i] - horizontalCuts[i-1]
for i in range(1, len(horizontalCuts)))
max_width = max(verticalCuts[i] - verticalCuts[i-1]
for i in range(1, len(verticalCuts)))
# Return result with modulo
return (max_height * max_width) % (10**9 + 7)
Given a sorted array of integers and an integer called target, find the element that
equals to the target and return its index. Select the correct code that fills the
___
in the given code snippet.
1def binary_search(arr, target):
2 left, right = 0, len(arr) - 1
3 while left ___ right:
4 mid = (left + right) // 2
5 if arr[mid] == target:
6 return mid
7 if arr[mid] < target:
8 ___ = mid + 1
9 else:
10 ___ = mid - 1
11 return -1
12
1public static int binarySearch(int[] arr, int target) {
2 int left = 0;
3 int right = arr.length - 1;
4
5 while (left ___ right) {
6 int mid = left + (right - left) / 2;
7 if (arr[mid] == target) return mid;
8 if (arr[mid] < target) {
9 ___ = mid + 1;
10 } else {
11 ___ = mid - 1;
12 }
13 }
14 return -1;
15}
16
1function binarySearch(arr, target) {
2 let left = 0;
3 let right = arr.length - 1;
4
5 while (left ___ right) {
6 let mid = left + Math.trunc((right - left) / 2);
7 if (arr[mid] == target) return mid;
8 if (arr[mid] < target) {
9 ___ = mid + 1;
10 } else {
11 ___ = mid - 1;
12 }
13 }
14 return -1;
15}
16
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Donโt Miss This!