You are given three integers m
, n
, and k
.
There is a rectangular grid of size m × n
containing k
identical pieces. Return the sum of Manhattan distances between every pair of pieces over all valid arrangements of pieces.
A valid arrangement is a placement of all k
pieces on the grid with at most one piece per cell.
Since the answer may be very large, return it modulo 109 + 7
.
The Manhattan Distance between two cells (xi, yi)
and (xj, yj)
is |xi - xj| + |yi - yj|
.
Example 1:
Input: m = 2, n = 2, k = 2
Output: 8
Explanation:
The valid arrangements of pieces on the board are:
Thus, the total Manhattan distance across all valid arrangements is 1 + 1 + 1 + 1 + 2 + 2 = 8
.
Example 2:
Input: m = 1, n = 4, k = 3
Output: 20
Explanation:
The valid arrangements of pieces on the board are:
1 + 1 + 2 = 4
.1 + 2 + 3 = 6
.The total Manhattan distance between all pairs of pieces across all arrangements is 4 + 6 + 6 + 4 = 20
.
Constraints:
1 <= m, n <= 105
2 <= m * n <= 105
2 <= k <= m * n
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach involves trying every possible arrangement of pieces on the board. For each arrangement, we calculate the total Manhattan distance and keep track of the minimum we find across all arrangements. It's like trying every possible layout to find the one with the smallest distance.
Here's how the algorithm would work step-by-step:
import itertools
def manhattan_distance(point_one, point_two):
return abs(point_one[0] - point_two[0]) + abs(point_one[1] - point_two[1])
def total_manhattan_distance(arrangement):
total_distance = 0
number_of_pieces = len(arrangement)
for i in range(number_of_pieces):
for j in range(i + 1, number_of_pieces):
total_distance += manhattan_distance(arrangement[i], arrangement[j])
return total_distance
def find_min_manhattan_distance_brute_force(piece_positions):
# Initialize minimum distance to infinity.
minimum_total_distance = float('inf')
# Generate all possible arrangements of piece positions.
all_arrangements = list(itertools.permutations(piece_positions))
# Iterate through all arrangements.
for arrangement in all_arrangements:
# Calculate total Manhattan distance for current arrangement.
current_total_distance = total_manhattan_distance(arrangement)
# Update minimum distance if current distance is smaller.
if current_total_distance < minimum_total_distance:
minimum_total_distance = current_total_distance
return minimum_total_distance
The problem asks us to find the total Manhattan distance for every possible arrangement of pieces. Instead of generating every arrangement and calculating its Manhattan distance (which would take way too long), we can cleverly use math and combinatorics to figure out the total distance efficiently.
Here's how the algorithm would work step-by-step:
def manhattan_distances(coordinates):
number_of_pieces = len(coordinates)
total_arrangements = 1
for i in range(1, number_of_pieces + 1):
total_arrangements *= i
total_manhattan_distance = 0
# Calculate Manhattan distance for x coordinates.
x_coordinates = [x for x, y in coordinates]
total_manhattan_distance += calculate_coordinate_distance(x_coordinates, total_arrangements)
# Calculate Manhattan distance for y coordinates.
y_coordinates = [y for x, y in coordinates]
total_manhattan_distance += calculate_coordinate_distance(y_coordinates, total_arrangements)
return total_manhattan_distance
def calculate_coordinate_distance(coordinate_list, total_arrangements):
number_of_pieces = len(coordinate_list)
total_coordinate_distance = 0
# Iterate through all pairs of pieces.
for i in range(number_of_pieces):
for j in range(i + 1, number_of_pieces):
# Calculate coordinate difference for the pair.
coordinate_difference = abs(coordinate_list[i] - coordinate_list[j])
#Calculate how many times the pair will be swapped.
number_of_swaps = total_arrangements // (number_of_pieces * (number_of_pieces - 1) // 2)
# Accumulate the distance
total_coordinate_distance += coordinate_difference * number_of_swaps
return total_coordinate_distance
Case | How to Handle |
---|---|
Null or empty input array | Return an empty list or an appropriate error code indicating invalid input to prevent null pointer exceptions or incorrect calculations. |
Array with only one piece | Return an empty list since no pairs can be formed to calculate Manhattan distances. |
All pieces located at the same coordinate | The Manhattan distance between all pairs will be 0, which the algorithm should correctly compute. |
Maximum array size leading to integer overflow during distance calculation | Use a larger data type (e.g., long) for distance calculations to prevent integer overflow if Manhattan distance can exceed the maximum value of int. |
Very large coordinate values leading to integer overflow | Use long data types for storing coordinates or implement overflow checks during distance calculation. |
Duplicate piece positions | The permutation logic should handle duplicate piece positions correctly by generating all distinct arrangements regardless of duplicates. |
Large number of pieces causing the permutation generation to become extremely slow | The algorithm's time complexity is factorial, so for large input sizes, return an error message/null value after exceeding a set number of recursions or implement an approximate heuristic if an exact solution isn't strictly required. |
Negative coordinate values | The Manhattan distance calculation |x1-x2| + |y1-y2| handles negative coordinates correctly without requiring special treatment. |