2975. Maximum Square Area by Removing Fences From a Field
Problem Description
You have a rectangular field with corners at coordinates (1, 1)
and (m, n)
. The field contains some internal fences:
- Horizontal fences run from
(hFences[i], 1)
to(hFences[i], n)
- Vertical fences run from
(1, vFences[i])
to(m, vFences[i])
The field is also surrounded by boundary fences that cannot be removed:
- Two horizontal boundaries: from
(1, 1)
to(1, n)
and from(m, 1)
to(m, n)
- Two vertical boundaries: from
(1, 1)
to(m, 1)
and from(1, n)
to(m, n)
Your task is to find the maximum area of a square field that can be created by removing some (or none) of the internal fences. The square must be formed by selecting two horizontal lines (either boundaries or fences) and two vertical lines (either boundaries or fences) such that the distance between the horizontal lines equals the distance between the vertical lines.
Return the maximum square area modulo 10^9 + 7
. If no square field can be formed, return -1
.
For example, if you can create a square with side length d
, the area would be d^2
. You need to find the largest possible d
where:
- The distance
d
exists between some pair of horizontal lines (considering both boundaries and fences) - The same distance
d
exists between some pair of vertical lines (considering both boundaries and fences)
Intuition
To form a square field, we need to find two horizontal lines that are distance d
apart and two vertical lines that are also distance d
apart. The key insight is that we don't need to track which specific fences we remove - we only care about what distances are achievable.
Think of it this way: if we have horizontal fences at positions [2, 5, 7]
plus boundaries at 1
and m
, we can create various distances by choosing any two of these positions. For instance, choosing positions 2
and 7
gives us a distance of 5
. Similarly for vertical fences.
The crucial observation is that a square with side length d
can be formed if and only if:
- Distance
d
can be achieved between some pair of horizontal lines (including boundaries) - The same distance
d
can be achieved between some pair of vertical lines (including boundaries)
This naturally leads to a set intersection approach:
- Calculate all possible distances between pairs of horizontal lines (including boundaries at
1
andm
) - Calculate all possible distances between pairs of vertical lines (including boundaries at
1
andn
) - Find the common distances that appear in both sets
- The largest common distance gives us the maximum square side length
Why does this work? Because if distance d
appears in both sets, it means we can select two horizontal lines d
units apart AND two vertical lines d
units apart, forming a square of side length d
. The area would then be d^2
.
The beauty of this approach is that it reduces a potentially complex geometric problem to a simple set operation - finding the intersection of two sets of distances and taking the maximum value.
Solution Approach
The solution implements the intuition using a helper function and set operations:
Step 1: Generate All Possible Distances
The helper function f(nums: List[int], k: int)
takes a list of fence positions and a boundary value k
:
- First, it extends the list with boundary positions
[1, k]
to include the field boundaries - Sorts the combined list to have positions in order
- Uses
combinations(nums, 2)
to generate all pairs of positions - Calculates the distance
b - a
for each pair(a, b)
wherea < b
(guaranteed by combinations on sorted list) - Returns a set containing all unique distances
Step 2: Calculate Horizontal and Vertical Distances
- Call
f(hFences, m)
to get all possible horizontal distanceshs
- This includes distances between any two horizontal lines (fences + boundaries at positions
1
andm
)
- This includes distances between any two horizontal lines (fences + boundaries at positions
- Call
f(vFences, n)
to get all possible vertical distancesvs
- This includes distances between any two vertical lines (fences + boundaries at positions
1
andn
)
- This includes distances between any two vertical lines (fences + boundaries at positions
Step 3: Find Common Distances
- Use set intersection
hs & vs
to find distances that appear in both sets - These common distances represent possible square side lengths
- Use
max(hs & vs, default=0)
to find the largest common distance- The
default=0
handles the case when there's no intersection (no square possible)
- The
Step 4: Calculate the Result
- If
ans
(maximum common distance) is non-zero:- Calculate the square area as
ans**2
- Return the result modulo
10**9 + 7
- Calculate the square area as
- If
ans
is0
(no common distances found):- Return
-1
to indicate no square field is possible
- Return
The time complexity is O(p^2 + q^2)
where p
and q
are the total number of horizontal and vertical lines respectively (including boundaries). The space complexity is O(p^2 + q^2)
for storing all possible distances in the sets.
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 where m = 6
, n = 7
, hFences = [3]
, and vFences = [4]
.
Step 1: Identify all horizontal lines
- Boundary lines at positions: 1 and 6
- Fence lines at position: 3
- All horizontal lines: [1, 3, 6]
Step 2: Calculate all possible horizontal distances
- Distance between positions 1 and 3:
3 - 1 = 2
- Distance between positions 1 and 6:
6 - 1 = 5
- Distance between positions 3 and 6:
6 - 3 = 3
- Set of horizontal distances:
{2, 3, 5}
Step 3: Identify all vertical lines
- Boundary lines at positions: 1 and 7
- Fence lines at position: 4
- All vertical lines: [1, 4, 7]
Step 4: Calculate all possible vertical distances
- Distance between positions 1 and 4:
4 - 1 = 3
- Distance between positions 1 and 7:
7 - 1 = 6
- Distance between positions 4 and 7:
7 - 4 = 3
- Set of vertical distances:
{3, 6}
Step 5: Find common distances
- Horizontal distances:
{2, 3, 5}
- Vertical distances:
{3, 6}
- Intersection:
{2, 3, 5} ∩ {3, 6} = {3}
- Maximum common distance: 3
Step 6: Calculate the result
- Maximum square side length: 3
- Maximum square area:
3² = 9
- Return:
9 % (10⁹ + 7) = 9
This means we can form a square field with side length 3. For instance:
- Using horizontal lines at positions 3 and 6 (distance = 3)
- Using vertical lines at positions 1 and 4 (distance = 3)
- Or using vertical lines at positions 4 and 7 (distance = 3)
The key insight is that we don't need to track which specific fences to remove - we only need to find matching distances in both horizontal and vertical directions to form a square.
Solution Implementation
1class Solution:
2 def maximizeSquareArea(
3 self, m: int, n: int, hFences: List[int], vFences: List[int]
4 ) -> int:
5 """
6 Find the maximum square area that can be formed in a field with fences.
7
8 Args:
9 m: Width of the field
10 n: Height of the field
11 hFences: List of horizontal fence positions
12 vFences: List of vertical fence positions
13
14 Returns:
15 Maximum square area modulo 10^9 + 7, or -1 if no square can be formed
16 """
17
18 def get_all_distances(fence_positions: List[int], field_size: int) -> Set[int]:
19 """
20 Calculate all possible distances between any two fence positions,
21 including the field boundaries.
22
23 Args:
24 fence_positions: List of fence positions
25 field_size: Size of the field dimension (width or height)
26
27 Returns:
28 Set of all possible distances between fence pairs
29 """
30 # Add field boundaries (1 and field_size) to fence positions
31 all_positions = fence_positions + [1, field_size]
32 # Sort positions for consistent processing
33 all_positions.sort()
34
35 # Calculate all possible distances between any two positions
36 distances = set()
37 for i in range(len(all_positions)):
38 for j in range(i + 1, len(all_positions)):
39 distance = all_positions[j] - all_positions[i]
40 distances.add(distance)
41
42 return distances
43
44 # Modulo value for the result
45 MOD = 10**9 + 7
46
47 # Get all possible horizontal distances
48 horizontal_distances = get_all_distances(hFences, m)
49
50 # Get all possible vertical distances
51 vertical_distances = get_all_distances(vFences, n)
52
53 # Find common distances (these can form squares)
54 common_distances = horizontal_distances & vertical_distances
55
56 # Get the maximum common distance (largest square side length)
57 max_side_length = max(common_distances, default=0)
58
59 # Calculate and return the area
60 if max_side_length > 0:
61 area = (max_side_length ** 2) % MOD
62 return area
63 else:
64 # No square can be formed
65 return -1
66
1class Solution {
2 public int maximizeSquareArea(int m, int n, int[] hFences, int[] vFences) {
3 // Get all possible horizontal distances between fences (including boundaries)
4 Set<Integer> horizontalDistances = calculateAllDistances(hFences, m);
5
6 // Get all possible vertical distances between fences (including boundaries)
7 Set<Integer> verticalDistances = calculateAllDistances(vFences, n);
8
9 // Find common distances that can form squares (equal horizontal and vertical sides)
10 horizontalDistances.retainAll(verticalDistances);
11
12 // Find the maximum square side length
13 int maxSideLength = -1;
14 final int MOD = (int) 1e9 + 7;
15
16 for (int sideLength : horizontalDistances) {
17 maxSideLength = Math.max(maxSideLength, sideLength);
18 }
19
20 // Calculate and return the area of the maximum square, or -1 if no square is possible
21 return maxSideLength > 0 ? (int) (1L * maxSideLength * maxSideLength % MOD) : -1;
22 }
23
24 /**
25 * Calculate all possible distances between fence positions including boundaries
26 * @param fences Array of fence positions
27 * @param boundaryPosition The boundary position (m for horizontal, n for vertical)
28 * @return Set of all possible distances between any two positions
29 */
30 private Set<Integer> calculateAllDistances(int[] fences, int boundaryPosition) {
31 int fenceCount = fences.length;
32
33 // Create a new array including the original fences and two boundaries (1 and boundaryPosition)
34 int[] allPositions = Arrays.copyOf(fences, fenceCount + 2);
35 allPositions[fenceCount] = 1; // Starting boundary
36 allPositions[fenceCount + 1] = boundaryPosition; // Ending boundary
37
38 // Sort positions to calculate distances efficiently
39 Arrays.sort(allPositions);
40
41 // Store all possible distances between any two positions
42 Set<Integer> distances = new HashSet<>();
43
44 // Calculate distance between every pair of positions
45 for (int i = 0; i < allPositions.length; ++i) {
46 for (int j = 0; j < i; ++j) {
47 distances.add(allPositions[i] - allPositions[j]);
48 }
49 }
50
51 return distances;
52 }
53}
54
1class Solution {
2public:
3 int maximizeSquareArea(int m, int n, vector<int>& hFences, vector<int>& vFences) {
4 // Lambda function to calculate all possible distances between fence positions
5 auto calculateDistances = [](vector<int>& fences, int boundary) -> unordered_set<int> {
6 // Add the boundary positions (1 and boundary) to the fence list
7 fences.push_back(boundary);
8 fences.push_back(1);
9
10 // Sort all fence positions for systematic distance calculation
11 sort(fences.begin(), fences.end());
12
13 // Store all possible distances in a set
14 unordered_set<int> distances;
15
16 // Calculate distance between every pair of fence positions
17 for (int i = 0; i < fences.size(); ++i) {
18 for (int j = 0; j < i; ++j) {
19 distances.insert(fences[i] - fences[j]);
20 }
21 }
22
23 return distances;
24 };
25
26 // Calculate all possible horizontal distances
27 unordered_set<int> horizontalDistances = calculateDistances(hFences, m);
28
29 // Calculate all possible vertical distances
30 unordered_set<int> verticalDistances = calculateDistances(vFences, n);
31
32 // Find the maximum distance that exists in both horizontal and vertical sets
33 int maxSideLength = 0;
34 for (int distance : horizontalDistances) {
35 // Check if this distance can form a square (exists in both dimensions)
36 if (verticalDistances.count(distance)) {
37 maxSideLength = max(maxSideLength, distance);
38 }
39 }
40
41 // Define modulo for the result
42 const int MOD = 1e9 + 7;
43
44 // Return the area of the largest square, or -1 if no square is possible
45 return maxSideLength > 0 ? (1LL * maxSideLength * maxSideLength) % MOD : -1;
46 }
47};
48
1/**
2 * Calculates the maximum square area that can be formed using the given fences
3 * @param m - The maximum horizontal boundary
4 * @param n - The maximum vertical boundary
5 * @param hFences - Array of horizontal fence positions
6 * @param vFences - Array of vertical fence positions
7 * @returns The area of the largest square modulo 1000000007, or -1 if no square can be formed
8 */
9function maximizeSquareArea(m: number, n: number, hFences: number[], vFences: number[]): number {
10 /**
11 * Helper function to calculate all possible distances between fence positions
12 * @param fencePositions - Array of fence positions
13 * @param boundary - The maximum boundary value
14 * @returns Set of all possible distances between any two positions
15 */
16 const calculateDistances = (fencePositions: number[], boundary: number): Set<number> => {
17 // Add the start (1) and end (boundary) positions to the fence array
18 fencePositions.push(1, boundary);
19
20 // Sort positions in ascending order
21 fencePositions.sort((a, b) => a - b);
22
23 // Store all possible distances
24 const distances: Set<number> = new Set();
25
26 // Calculate distance between every pair of positions
27 for (let i = 0; i < fencePositions.length; ++i) {
28 for (let j = 0; j < i; ++j) {
29 distances.add(fencePositions[i] - fencePositions[j]);
30 }
31 }
32
33 return distances;
34 };
35
36 // Calculate all possible horizontal distances
37 const horizontalDistances = calculateDistances(hFences, m);
38
39 // Calculate all possible vertical distances
40 const verticalDistances = calculateDistances(vFences, n);
41
42 // Find the maximum side length that exists in both horizontal and vertical distances
43 let maxSideLength = 0;
44 for (const horizontalDistance of horizontalDistances) {
45 // Check if this distance can form a square (exists in both dimensions)
46 if (verticalDistances.has(horizontalDistance)) {
47 maxSideLength = Math.max(maxSideLength, horizontalDistance);
48 }
49 }
50
51 // Calculate the area and return with modulo, or -1 if no square found
52 const MOD = 1000000007n;
53 return maxSideLength ? Number(BigInt(maxSideLength) ** 2n % MOD) : -1;
54}
55
Time and Space Complexity
The time complexity is O(h^2 + v^2)
, where h
is the length of hFences
and v
is the length of vFences
.
Breaking down the analysis:
- The function
f
is called twice - once for horizontal fences and once for vertical fences - Inside function
f
, after extending the list with 2 elements (boundaries), we haveh+2
horizontal positions andv+2
vertical positions - Sorting takes
O((h+2)log(h+2))
for horizontal andO((v+2)log(v+2))
for vertical - The combinations operation generates all pairs from the sorted list, which creates
C(h+2, 2) = (h+2)(h+1)/2
pairs for horizontal andC(v+2, 2) = (v+2)(v+1)/2
pairs for vertical - Computing differences for all pairs takes
O(h^2)
for horizontal andO(v^2)
for vertical - The set intersection operation
hs & vs
takesO(min(|hs|, |vs|))
which is bounded byO(h^2 + v^2)
- Finding the maximum takes linear time in the size of the intersection
Since O(h^2)
and O(v^2)
dominate the sorting operations, the overall time complexity is O(h^2 + v^2)
.
The space complexity is O(h^2 + v^2)
:
- The set
hs
stores up to(h+2)(h+1)/2
differences, which isO(h^2)
- The set
vs
stores up to(v+2)(v+1)/2
differences, which isO(v^2)
- The intersection creates a new set with size at most
min(|hs|, |vs|)
- Other variables use constant space
Therefore, the total space complexity is O(h^2 + v^2)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Integer Overflow When Calculating Square Area
The most critical pitfall in this problem is calculating max_side_length ** 2
without considering integer overflow. Since the field dimensions can be as large as 10^9
, the maximum possible side length is also up to 10^9
. When squaring this value, we get 10^18
, which exceeds the typical 32-bit integer limit and can cause overflow issues in some programming languages.
Incorrect approach:
# This might cause issues in languages with fixed integer sizes area = max_side_length ** 2 return area % MOD
Correct approach:
# Apply modulo during calculation to prevent overflow
area = pow(max_side_length, 2, MOD) # Built-in modular exponentiation
# Or explicitly handle large numbers
area = (max_side_length * max_side_length) % MOD
2. Forgetting to Include Boundary Fences
A common mistake is only considering the internal fences and forgetting that the field boundaries at positions 1
and m
(for horizontal) and 1
and n
(for vertical) are also valid lines for forming squares.
Incorrect approach:
# Only using internal fences
distances = set()
for i in range(len(hFences)):
for j in range(i + 1, len(hFences)):
distances.add(hFences[j] - hFences[i])
Correct approach:
# Include boundaries with internal fences all_positions = hFences + [1, m] # Add boundaries all_positions.sort() # Then calculate distances from all positions
3. Not Handling Empty Intersection Properly
When there are no common distances between horizontal and vertical possibilities, the intersection will be empty. Using max()
on an empty set will raise a ValueError
.
Incorrect approach:
max_side_length = max(horizontal_distances & vertical_distances) # Raises error if empty
Correct approach:
max_side_length = max(horizontal_distances & vertical_distances, default=0)
# Or check explicitly:
common_distances = horizontal_distances & vertical_distances
if not common_distances:
return -1
max_side_length = max(common_distances)
4. Inefficient Distance Calculation
Using nested loops without optimization or using combinations incorrectly can lead to inefficiency or errors.
Less efficient approach:
# Creating unnecessary intermediate lists
from itertools import combinations
all_pairs = list(combinations(all_positions, 2))
distances = set([b - a for a, b in all_pairs])
More efficient approach:
# Direct set construction without intermediate list
distances = {b - a for a, b in combinations(sorted(all_positions), 2)}
5. Not Sorting Positions Before Distance Calculation
If positions aren't sorted, you might calculate negative distances or need additional checks.
Incorrect approach:
# Without sorting, might get negative distances
for a, b in combinations(all_positions, 2):
distances.add(abs(b - a)) # Need abs() to handle order
Correct approach:
all_positions.sort() # Sort first for a, b in combinations(all_positions, 2): distances.add(b - a) # No need for abs() since b > a is guaranteed
Which of the following shows the order of node visit in a Breadth-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!