Facebook Pixel

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.

  1. 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.

  2. 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.

Learn more about Greedy and Sorting patterns.

Solution Approach

In the given solution, the problem is tackled using a greedy algorithm. The implementation involves the following steps:

  1. 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), where x is the current x-coordinate of the rook and i 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))
  2. 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) where y is the current y-coordinate and j 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))
  3. 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 Evaluator

Example 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.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

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

Want a Structured Path to Master System Design Too? Donโ€™t Miss This!


Load More