1725. Number Of Rectangles That Can Form The Largest Square
Problem Description
You are given an array rectangles
where each element rectangles[i] = [li, wi]
represents a rectangle with length li
and width wi
.
From each rectangle, you can cut out a square. The maximum side length of the square you can cut from a rectangle is limited by the smaller dimension of that rectangle. Specifically, from a rectangle with dimensions [l, w]
, you can cut a square with side length k
only if k ≤ l
and k ≤ w
. This means the maximum square you can cut has a side length of min(l, w)
.
For example, if you have a rectangle [4, 6]
, the largest square you can cut from it has a side length of 4
(the minimum of 4 and 6).
Your task is to:
- Find the maximum side length (
maxLen
) among all possible squares that can be cut from all the given rectangles - Count how many rectangles can produce a square with this maximum side length
The function should return the count of rectangles that can make a square with side length equal to maxLen
.
Example walkthrough:
- If
rectangles = [[5,8], [3,9], [5,12], [16,5]]
- Rectangle
[5,8]
can make a square with max side length5
- Rectangle
[3,9]
can make a square with max side length3
- Rectangle
[5,12]
can make a square with max side length5
- Rectangle
[16,5]
can make a square with max side length5
- The maximum side length among all is
5
, and three rectangles can produce this, so the answer is3
Intuition
The key insight is that for each rectangle, the largest square we can cut from it is determined by its smaller dimension. If a rectangle has dimensions [l, w]
, then the maximum square side length is min(l, w)
because the square must fit within both dimensions.
Once we understand this, the problem becomes straightforward: we need to find the maximum value among all these minimum dimensions, then count how many rectangles can produce this maximum value.
We can solve this efficiently in a single pass through the array. As we examine each rectangle:
- Calculate the maximum square side length for that rectangle:
x = min(l, w)
- Compare this with our current maximum (
mx
):- If we find a larger value (
x > mx
), we've discovered a new maximum. Reset our count to 1 and update the maximum. - If we find an equal value (
x == mx
), we've found another rectangle that can produce the same maximum square. Increment our count. - If we find a smaller value (
x < mx
), we ignore it as it doesn't affect our answer.
- If we find a larger value (
This approach allows us to track both the maximum square side length and the count of rectangles that can achieve it in a single traversal, making it an O(n) solution with O(1) extra space.
The elegance of this solution lies in maintaining just two variables (mx
for the maximum side length and ans
for the count) and updating them appropriately as we scan through the rectangles once.
Solution Approach
The solution uses a single-pass algorithm with two tracking variables to solve the problem efficiently.
Implementation Details:
-
Initialize tracking variables:
ans = 0
: Counts the number of rectangles that can produce the maximum squaremx = 0
: Tracks the current maximum square side length found
-
Process each rectangle: For each rectangle
[l, w]
in the array:- Calculate the maximum square side length:
x = min(l, w)
- This represents the largest square that can be cut from this rectangle
- Calculate the maximum square side length:
-
Update the tracking variables based on comparison:
- Case 1: Found a larger square (
mx < x
)- Update
mx = x
to record the new maximum - Reset
ans = 1
since this is the first rectangle with this new maximum size
- Update
- Case 2: Found an equal square (
mx == x
)- Increment
ans += 1
since we found another rectangle that can produce the maximum square
- Increment
- Case 3: Found a smaller square (
mx > x
)- Do nothing (implicitly handled by not having an else clause)
- Case 1: Found a larger square (
-
Return the result: After processing all rectangles,
ans
contains the count of rectangles that can produce the maximum square side length.
Time Complexity: O(n) where n is the number of rectangles, as we traverse the array once.
Space Complexity: O(1) as we only use two variables regardless of input size.
The algorithm efficiently combines the search for the maximum value and counting occurrences of that maximum in a single pass, eliminating the need for a two-pass approach (first finding the maximum, then counting).
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example with rectangles = [[2,3], [3,7], [4,3], [3,3]]
Initial state:
mx = 0
(maximum square side length found so far)ans = 0
(count of rectangles that can produce the maximum square)
Step 1: Process rectangle [2,3]
- Maximum square from this rectangle:
x = min(2,3) = 2
- Compare with current maximum:
mx = 0 < x = 2
- Since we found a larger square, update:
mx = 2
(new maximum)ans = 1
(first rectangle with this size)
Step 2: Process rectangle [3,7]
- Maximum square from this rectangle:
x = min(3,7) = 3
- Compare with current maximum:
mx = 2 < x = 3
- Since we found an even larger square, update:
mx = 3
(new maximum)ans = 1
(reset count for new maximum)
Step 3: Process rectangle [4,3]
- Maximum square from this rectangle:
x = min(4,3) = 3
- Compare with current maximum:
mx = 3 == x = 3
- Since this equals our current maximum, increment:
mx = 3
(unchanged)ans = 2
(second rectangle with this size)
Step 4: Process rectangle [3,3]
- Maximum square from this rectangle:
x = min(3,3) = 3
- Compare with current maximum:
mx = 3 == x = 3
- Since this also equals our current maximum, increment:
mx = 3
(unchanged)ans = 3
(third rectangle with this size)
Final Result: Return ans = 3
The maximum square side length is 3, and three rectangles ([3,7], [4,3], and [3,3]) can produce a square of this size.
Solution Implementation
1class Solution:
2 def countGoodRectangles(self, rectangles: List[List[int]]) -> int:
3 # Initialize counter and maximum square side length
4 count = 0
5 max_side = 0
6
7 # Iterate through each rectangle
8 for length, width in rectangles:
9 # Find the maximum square that can fit in this rectangle
10 # The side length is limited by the smaller dimension
11 square_side = min(length, width)
12
13 # If we found a larger square, reset count to 1
14 if square_side > max_side:
15 count = 1
16 max_side = square_side
17 # If square has same size as current maximum, increment count
18 elif square_side == max_side:
19 count += 1
20
21 return count
22
1class Solution {
2 public int countGoodRectangles(int[][] rectangles) {
3 int count = 0; // Counter for rectangles with maximum square side length
4 int maxSideLength = 0; // Maximum square side length found so far
5
6 // Iterate through each rectangle in the array
7 for (int[] rectangle : rectangles) {
8 // Calculate the side length of the largest square that can fit in this rectangle
9 // The square's side length is limited by the smaller dimension of the rectangle
10 int squareSideLength = Math.min(rectangle[0], rectangle[1]);
11
12 // Check if we found a new maximum square side length
13 if (squareSideLength > maxSideLength) {
14 maxSideLength = squareSideLength; // Update the maximum side length
15 count = 1; // Reset count to 1 for this new maximum
16 }
17 // Check if current square matches the maximum side length
18 else if (squareSideLength == maxSideLength) {
19 count++; // Increment count for rectangles with same maximum square
20 }
21 }
22
23 return count; // Return the total count of rectangles with maximum square side length
24 }
25}
26
1class Solution {
2public:
3 int countGoodRectangles(vector<vector<int>>& rectangles) {
4 int count = 0; // Counter for rectangles with maximum square side length
5 int maxSideLength = 0; // Maximum square side length found so far
6
7 // Iterate through each rectangle
8 for (auto& rectangle : rectangles) {
9 // Calculate the maximum square side that can fit in current rectangle
10 // The side length is limited by the smaller dimension
11 int currentMaxSquareSide = min(rectangle[0], rectangle[1]);
12
13 // Check if we found a new maximum
14 if (currentMaxSquareSide > maxSideLength) {
15 maxSideLength = currentMaxSquareSide; // Update the maximum
16 count = 1; // Reset count to 1
17 }
18 // Check if current square matches the maximum
19 else if (currentMaxSquareSide == maxSideLength) {
20 ++count; // Increment count of rectangles with max square side
21 }
22 }
23
24 return count;
25 }
26};
27
1/**
2 * Counts the number of rectangles that can form the largest square
3 * @param rectangles - Array of rectangles where each rectangle is represented as [length, width]
4 * @returns The count of rectangles that can form the maximum square
5 */
6function countGoodRectangles(rectangles: number[][]): number {
7 // Initialize count of maximum squares and the maximum square side length
8 let count: number = 0;
9 let maxSquareSide: number = 0;
10
11 // Iterate through each rectangle
12 for (const [length, width] of rectangles) {
13 // The maximum square that can fit in a rectangle has side length equal to the minimum dimension
14 const currentSquareSide: number = Math.min(length, width);
15
16 // If we found a larger square, update the maximum and reset count to 1
17 if (currentSquareSide > maxSquareSide) {
18 maxSquareSide = currentSquareSide;
19 count = 1;
20 }
21 // If current square equals the maximum, increment the count
22 else if (currentSquareSide === maxSquareSide) {
23 count++;
24 }
25 }
26
27 return count;
28}
29
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the array rectangles
. The algorithm iterates through each rectangle exactly once, performing constant-time operations (finding minimum, comparison, and increment) for each element.
The space complexity is O(1)
. The algorithm only uses a fixed amount of extra space with variables ans
, mx
, x
, l
, and w
, regardless of the input size. No additional data structures that grow with the input are created.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Incorrectly Resetting the Counter
The Mistake: A common error is forgetting to reset the counter when finding a new maximum, leading to incorrect counting:
# INCORRECT implementation
def countGoodRectangles(self, rectangles: List[List[int]]) -> int:
count = 0
max_side = 0
for length, width in rectangles:
square_side = min(length, width)
if square_side > max_side:
# Forgot to reset count!
max_side = square_side
elif square_side == max_side:
count += 1
return count
This would accumulate counts from previous smaller maximums, giving wrong results.
The Fix: Always reset the counter to 1 when discovering a new maximum:
if square_side > max_side: count = 1 # Reset to 1, not 0 max_side = square_side
Pitfall 2: Off-by-One Error in Counter Initialization
The Mistake:
Starting with count = 1
or resetting to 0
instead of 1
when finding a new maximum:
# INCORRECT - resetting to 0 if square_side > max_side: count = 0 # Wrong! Should be 1 max_side = square_side elif square_side == max_side: count += 1
This misses counting the first rectangle that establishes the new maximum.
Pitfall 3: Using Max Instead of Min for Square Side
The Mistake:
Using max(length, width)
instead of min(length, width)
:
# INCORRECT
square_side = max(length, width) # Wrong!
A square must fit within both dimensions, so we need the minimum, not maximum.
Pitfall 4: Handling Edge Cases Incorrectly
The Mistake: Not considering empty input or assuming all dimensions are positive:
def countGoodRectangles(self, rectangles: List[List[int]]) -> int:
if not rectangles: # Edge case handling
return 0
count = 0
max_side = 0
for length, width in rectangles:
# Could add validation here if needed
if length <= 0 or width <= 0:
continue
square_side = min(length, width)
# ... rest of logic
Best Practice Solution: The correct approach maintains clear logic for all three cases:
def countGoodRectangles(self, rectangles: List[List[int]]) -> int:
count = 0
max_side = 0
for length, width in rectangles:
square_side = min(length, width)
if square_side > max_side:
count = 1 # Found new maximum, reset to 1
max_side = square_side
elif square_side == max_side:
count += 1 # Found another with same max size
# implicitly: if square_side < max_side, do nothing
return count
Which of these pictures shows the visit order of a depth-first search?
Recommended Readings
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
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!