3189. Minimum Moves to Get a Peaceful Board ๐
Problem Description
Given a 2D array rooks
of length n
, where rooks[i] = [x_i, y_i]
indicates the position of a rook on an n x n
chess board. Your task is to move the rooks 1 cell at a time vertically or horizontally (to an adjacent cell) such that the board becomes peaceful.
A board is considered peaceful if there is exactly one rook in each row and each column.
Return the minimum number of moves required to achieve a peaceful board.
Note that at no point can there be two rooks in the same cell.
Intuition
The problem can be solved efficiently using a greedy approach. The key insight is that by arranging rooks in increasing order of their coordinates, we can minimize the total distance traveled to reach a peaceful arrangement.
-
Sorting by X-coordinates: First, sort all the rooks based on their x-coordinates. This allows us to iterate over them and align them with their respective row indices (0 through n-1). By computing the sum of the absolute differences between each rookโs x-coordinate and its target x-coordinate (the index), we determine the total moves needed just to position them correctly in rows.
-
Sorting by Y-coordinates: Perform a similar process for y-coordinates. After sorting rooks by the y-coordinate, align them with their column indices, and compute the moves required to achieve this alignment.
The final result is the sum of moves required for both x and y alignments. This ensures a peaceful board with one rook per row and one per column while achieving it in the minimum number of moves.
Solution Approach
In the given solution, the problem is tackled using a greedy algorithm. The implementation involves the following steps:
-
Sorting by X-coordinates:
- First, sort the list of
rooks
based on their x-coordinates. - Iterate over each rook and compute the difference between its current x-coordinate and its target x-coordinate (which corresponds to its index in the sorted list).
- This difference is calculated using the formula
abs(x - i)
, wherex
is the current x-coordinate of the rook andi
is its index in the list. - Sum these absolute differences to get the total number of moves required to properly align the rooks in their respective rows.
rooks.sort() ans = sum(abs(x - i) for i, (x, _) in enumerate(rooks))
- First, sort the list of
-
Sorting by Y-coordinates:
- Sort the list of
rooks
based on their y-coordinates. - Similar to the x-coordinate alignment, calculate the difference between the current y-coordinate and the target y-coordinate for each rook.
- This is done using
abs(y - j)
wherey
is the current y-coordinate andj
is its index in the sorted list. - Add these differences to the previously calculated total to account for column alignment moves.
rooks.sort(key=lambda x: x[1]) ans += sum(abs(y - j) for j, (_, y) in enumerate(rooks))
- Sort the list of
-
Return the Result: The variable
ans
now contains the total minimum number of moves required to make the board peaceful.return ans
Overall, this approach efficiently ensures that each rook is moved to a position where there is exactly one rook per row and per column, minimizing the move count.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider a small example to illustrate the solution approach.
Example Input:
- Rooks positions:
rooks = [[0, 2], [1, 0], [2, 1]]
- Board size:
3 x 3
In this example, we have rooks at three positions: (0, 2), (1, 0), and (2, 1).
Step 1: Sorting by X-coordinates
Initially, the rooks are sorted by their x-coordinates:
[0, 2]
(Rook at (0, 2))[1, 0]
(Rook at (1, 0))[2, 1]
(Rook at (2, 1))
Since they are already in increasing order of their x-coordinates, the target x-coordinates simply match their indices:
- Rook at position (0, 2) aligns with row 0, needing
abs(0 - 0) = 0
moves. - Rook at position (1, 0) aligns with row 1, needing
abs(1 - 1) = 0
moves. - Rook at position (2, 1) aligns with row 2, needing
abs(2 - 2) = 0
moves.
Total x-coordinate alignment moves: 0 + 0 + 0 = 0
.
Step 2: Sorting by Y-coordinates
Next, sort the rooks by their y-coordinates:
[1, 0]
(Rook at (1, 0))[2, 1]
(Rook at (2, 1))[0, 2]
(Rook at (0, 2))
Align them with their column indices:
- Rook moves to (1, 0) for column 0, needing
abs(0 - 0) = 0
additional moves. - Rook moves to (2, 1) for column 1, needing
abs(1 - 1) = 0
additional moves. - Rook moves to (0, 2) for column 2, needing
abs(2 - 2) = 0
additional moves.
Total y-coordinate alignment moves: 0 + 0 + 0 = 0
.
Step 3: Return the Result
The total minimum number of moves required:
- Total moves = X-alignment moves + Y-alignment moves =
0 + 0 = 0
.
Thus, the peaceful arrangement is already achieved with 0
moves.
def min_rook_moves(rooks):
rooks.sort()
ans = sum(abs(x - i) for i, (x, _) in enumerate(rooks))
rooks.sort(key=lambda x: x[1])
ans += sum(abs(y - j) for j, (_, y) in enumerate(rooks))
return ans
rooks = [[0, 2], [1, 0], [2, 1]]
print(min_rook_moves(rooks)) # Output: 0
This walkthrough demonstrates how the given solution efficiently finds the minimal number of moves required to achieve a peaceful board configuration.
Solution Implementation
1from typing import List
2
3class Solution:
4 def minMoves(self, rooks: List[List[int]]) -> int:
5 # Step 1: Sort rooks by their x-coordinate (row number)
6 rooks.sort()
7
8 # Step 2: Calculate the total row movements needed
9 # Align each rook's x-coordinate to their target row (index in the sorted list)
10 row_moves = sum(abs(x - i) for i, (x, _) in enumerate(rooks))
11
12 # Step 3: Sort rooks by their y-coordinate (column number)
13 rooks.sort(key=lambda position: position[1])
14
15 # Step 4: Calculate the total column movements needed
16 # Align each rook's y-coordinate to their target column (index in the sorted list)
17 column_moves = sum(abs(y - j) for j, (_, y) in enumerate(rooks))
18
19 # Step 5: Return the total movements needed for both rows and columns
20 return row_moves + column_moves
21
1import java.util.Arrays;
2
3class Solution {
4 public int minMoves(int[][] rooks) {
5 // Sort the rooks array based on the rows (first coordinate).
6 Arrays.sort(rooks, (a, b) -> a[0] - b[0]);
7
8 int totalMoves = 0; // This will hold the overall number of moves required.
9 int n = rooks.length; // Number of rooks.
10
11 // Calculate the moves required to align rooks in rows sequentially.
12 for (int i = 0; i < n; ++i) {
13 // Calculate absolute distance from desired row position.
14 totalMoves += Math.abs(rooks[i][0] - i);
15 }
16
17 // Sort the rooks array based on the columns (second coordinate).
18 Arrays.sort(rooks, (a, b) -> a[1] - b[1]);
19
20 // Calculate the moves required to align rooks in columns sequentially.
21 for (int j = 0; j < n; ++j) {
22 // Calculate absolute distance from desired column position.
23 totalMoves += Math.abs(rooks[j][1] - j);
24 }
25
26 return totalMoves; // Return the calculated total minimum moves.
27 }
28}
29
1#include <vector>
2#include <algorithm>
3#include <cmath>
4
5class Solution {
6public:
7 int minMoves(std::vector<std::vector<int>>& rooks) {
8 // Sort rooks based on the x-coordinate
9 std::sort(rooks.begin(), rooks.end());
10
11 int totalMoves = 0; // Initialize the total number of moves
12 int n = rooks.size(); // Number of rooks
13
14 // Calculate moves required to align all rooks by x-coordinate
15 for (int i = 0; i < n; ++i) {
16 totalMoves += std::abs(rooks[i][0] - i); // Difference between position and index
17 }
18
19 // Sort rooks based on the y-coordinate using a custom comparator
20 std::sort(rooks.begin(), rooks.end(), [](const std::vector<int>& a, const std::vector<int>& b) {
21 return a[1] < b[1];
22 });
23
24 // Calculate moves required to align all rooks by y-coordinate
25 for (int j = 0; j < n; ++j) {
26 totalMoves += std::abs(rooks[j][1] - j); // Difference between position and index
27 }
28
29 return totalMoves; // Return the total moves required
30 }
31};
32
1function minMoves(rooks: number[][]): number {
2 // Sort rooks based on their row position (first coordinate)
3 rooks.sort((a, b) => a[0] - b[0]);
4
5 // Calculate total moves required to align rows
6 let ans = rooks.reduce((sum, rook, i) => {
7 return sum + Math.abs(rook[0] - i);
8 }, 0);
9
10 // Sort rooks based on their column position (second coordinate)
11 rooks.sort((a, b) => a[1] - b[1]);
12
13 // Add total moves required to align columns
14 ans += rooks.reduce((sum, rook, j) => {
15 return sum + Math.abs(rook[1] - j);
16 }, 0);
17
18 return ans; // Return the total minimum moves needed
19}
20
Time and Space Complexity
The time complexity of the code is O(n * log n)
due to the sorting operations on the list of rooks based on their x and y coordinates separately. Since sorting a list of length n
takes O(n * log n)
, and we perform sorting twice, the complexity remains O(n * log n)
.
The space complexity of the code is O(log n)
which comes from the space used by the sorting algorithm. This is typical for sorting algorithms like Timsort, used in Python, which operates in place but requires O(log n)
space for recursive calls or temporary storage.
Learn more about how to find time and space complexity quickly.
What is the best way of checking if an element exists in an unsorted array once in terms of time complexity? Select the best that applies.
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!