leetcode
leetcode 2701 ~ 2750
将石头分散到网格图的最少移动次数

将石头分散到网格图的最少移动次数

难度:

标签:

题目描述

You are given a 0-indexed 2D integer matrix grid of size 3 * 3, representing the number of stones in each cell. The grid contains exactly 9 stones, and there can be multiple stones in a single cell.

In one move, you can move a single stone from its current cell to any other cell if the two cells share a side.

Return the minimum number of moves required to place one stone in each cell.

 

Example 1:

Input: grid = [[1,1,0],[1,1,1],[1,2,1]]
Output: 3
Explanation: One possible sequence of moves to place one stone in each cell is: 
1- Move one stone from cell (2,1) to cell (2,2).
2- Move one stone from cell (2,2) to cell (1,2).
3- Move one stone from cell (1,2) to cell (0,2).
In total, it takes 3 moves to place one stone in each cell of the grid.
It can be shown that 3 is the minimum number of moves required to place one stone in each cell.

Example 2:

Input: grid = [[1,3,0],[1,0,0],[1,0,3]]
Output: 4
Explanation: One possible sequence of moves to place one stone in each cell is:
1- Move one stone from cell (0,1) to cell (0,2).
2- Move one stone from cell (0,1) to cell (1,1).
3- Move one stone from cell (2,2) to cell (1,2).
4- Move one stone from cell (2,2) to cell (2,1).
In total, it takes 4 moves to place one stone in each cell of the grid.
It can be shown that 4 is the minimum number of moves required to place one stone in each cell.

 

Constraints:

  • grid.length == grid[i].length == 3
  • 0 <= grid[i][j] <= 9
  • Sum of grid is equal to 9.

代码结果

运行时间: 55 ms, 内存: 16.2 MB


/*
 * Problem: Given a 3x3 grid where each cell contains a certain number of stones, find the minimum number of moves required to ensure each cell contains exactly one stone. A move involves transferring a stone to an adjacent cell with a common edge.
 * 
 * Approach (Java Stream):
 * 1. Identify cells with excess stones and cells lacking stones.
 * 2. Use streams to calculate the minimum distance to balance the stones.
 */
import java.util.*;
import java.util.stream.*;

public class Solution {
    public int minMoves(int[][] grid) {
        // List to store excess and deficit coordinates
        List<int[]> excess = new ArrayList<>();
        List<int[]> deficit = new ArrayList<>();
        
        // Populate excess and deficit lists using streams
        IntStream.range(0, 3).forEach(i ->
            IntStream.range(0, 3).forEach(j -> {
                if (grid[i][j] > 1) {
                    excess.add(new int[]{i, j, grid[i][j] - 1});
                } else if (grid[i][j] == 0) {
                    deficit.add(new int[]{i, j});
                }
            })
        );
        
        // Calculate minimum moves using excess and deficit
        return excess.stream().mapToInt(from ->
            deficit.stream().mapToInt(to ->
                (Math.abs(from[0] - to[0]) + Math.abs(from[1] - to[1])) * from[2]
            ).min().orElse(0)
        ).sum();
    }
}

解释

方法:

题目的目标是通过最少的移动,将每个格子中的石头数量均匀为一个。这个题解采用了深度优先搜索(DFS)的策略来尝试所有可能的石头移动方式。首先,题解通过两次遍历找出所有需要石头(即空格子)和多余石头的格子。然后,使用DFS尝试所有可能的从多余石头格子到空格子的移动方式,每次移动都更新当前的移动总次数,并在所有格子都被填满后记录最小的移动次数。DFS过程中,每次尝试将一个石头从一个有多余石头的格子移动到一个空格子,然后递归处理下一个空格子,直到所有空格子都被处理完毕。

时间复杂度:

O((M*N)^2)

空间复杂度:

O(N)

代码细节讲解

🦆
题解中提到使用DFS遍历所有可能的石头移动方式,那么在实际操作中如何确保每个空格子都能被适时地填满而不被遗漏?
在DFS的实现中,通过一个递归函数确保每个空格子被处理。函数中有一个递归的终止条件,当空格子的索引等于空格子总数时,表示所有空格子已被处理。每次递归调用都会尝试将一个石头从多余的格子移动到当前处理的空格子,并递归地处理下一个空格子,这样可以确保每个空格子都被逐一填满。
🦆
在DFS的实现中,如何避免重复处理相同的移动组合,以优化算法效率?
在当前的DFS实现中,避免重复处理相同的移动组合的策略主要依靠回溯。在每次递归调用之后,会将石头数恢复到移动前的状态,这种方式称为回溯。此外,更高效的策略可以包括使用记忆化来存储已经计算过的状态,或者使用更先进的搜索策略(如广度优先搜索)来减少不必要的重复搜索。
🦆
题解中提到将石头从有多余的格子移动到空格子,并在递归中处理下一个空格子,这种处理方式是否考虑了最短路径或最优移动策略?
题解中的DFS方法主要关注于尝试所有可能的移动,以找出完成任务的最少移动次数,而不是每次都寻找最短的单次移动路径。每次移动都计算距离并加到总移动次数中,但此策略并不保证每一步都是最优的。若要优化每次移动的效率,可以考虑引入贪心算法或启发式搜索(如A*算法)来优先考虑最有可能快速达到目标的移动。

相关问题