当前位置: 首页 > 工具软件 > Puzzle Game > 使用案例 >

773-Sliding Puzzle

徐皓君
2023-12-01

Description:
On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0.

A move consists of choosing 0 and a 4-directionally adjacent number and swapping it.

The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]].

Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1.

Examples:

Input: board = [[1,2,3],[4,0,5]]
Output: 1
Explanation: Swap the 0 and the 5 in one move.
Input: board = [[1,2,3],[5,4,0]]
Output: -1
Explanation: No number of moves will make the board solved.
Input: board = [[4,1,2],[5,0,3]]
Output: 5
Explanation: 5 is the smallest number of moves that solves the board.
An example path:
After move 0: [[4,1,2],[5,0,3]]
After move 1: [[4,1,2],[0,5,3]]
After move 2: [[0,1,2],[4,5,3]]
After move 3: [[1,0,2],[4,5,3]]
After move 4: [[1,2,0],[4,5,3]]
After move 5: [[1,2,3],[4,5,0]]
Input: board = [[3,2,4],[1,5,0]]
Output: 14

Note:

board will be a 2 x 3 array as described above.
board[i][j] will be a permutation of [0, 1, 2, 3, 4, 5].

解题思路:
使用BFS。问题的关键是高效的做BFS。

解法1,先看一个反例(我做的。。。):

class Solution {
    private static final int M = 2;
    private static final int N = 3;
    public int slidingPuzzle(int[][] board) {
        Set<Integer> set = new HashSet<>();
        Queue<int[][]> queue = new LinkedList<>();
        int[] dest = new int[]{1, 2, 3, 4, 5, 0};

        queue.offer(board);
        set.add(transform(board));
        int level = 0;
        while(!queue.isEmpty()){
            int size = queue.size();
            while(size > 0){
                int[][] node = queue.poll();
                if(valid(node, dest))   return level;
                int x = 0, y = 0;
                for(int i = 0;i < M;i++){
                    for(int j = 0;j < N;j++){
                        if(node[i][j] == 0){
                            x = i;
                            y = j;
                            break;
                        }
                    }
                }

                if(x - 1 >= 0){
                    int[][] newNode = new int[M][N];
                    for(int i = 0;i < M;i++){
                        for(int j = 0;j < N;j++){
                            newNode[i][j] = node[i][j];
                        }
                    }
                    int temp = newNode[x - 1][y];
                    newNode[x - 1][y] = newNode[x][y];
                    newNode[x][y] = temp;
                    if(set.add(transform(newNode)))    queue.offer(newNode);
                }
                if(x + 1 < M){
                    int[][] newNode = new int[M][N];
                    for(int i = 0;i < M;i++){
                        for(int j = 0;j < N;j++){
                            newNode[i][j] = node[i][j];
                        }
                    }
                    int temp = newNode[x + 1][y];
                    newNode[x + 1][y] = newNode[x][y];
                    newNode[x][y] = temp;
                    if(set.add(transform(newNode)))    queue.offer(newNode);
                }
                if(y - 1 >= 0){
                    int[][] newNode = new int[M][N];
                    for(int i = 0;i < M;i++){
                        for(int j = 0;j < N;j++){
                            newNode[i][j] = node[i][j];
                        }
                    }
                    int temp = newNode[x][y - 1];
                    newNode[x][y - 1] = newNode[x][y];
                    newNode[x][y] = temp;
                    if(set.add(transform(newNode)))    queue.offer(newNode);
                }
                if(y + 1 < N){
                    int[][] newNode = new int[M][N];
                    for(int i = 0;i < M;i++){
                        for(int j = 0;j < N;j++){
                            newNode[i][j] = node[i][j];
                        }
                    }
                    int temp = newNode[x][y + 1];
                    newNode[x][y + 1] = newNode[x][y];
                    newNode[x][y] = temp;
                    if(set.add(transform(newNode)))    queue.offer(newNode);
                }
                size--;
            }
            level++;
        }

        return -1;
    }
    public int transform(int[][] board){
        int sum = 1;

        for(int i = 0;i < M;i++){
            for(int j = 0;j < N;j++){
                sum = sum * 7 + board[i][j];
            }
        }

        return sum;
    }    

    public boolean valid(int[][] board, int[] dest){
        for(int i = 0;i < M;i++){
            for(int j = 0;j < N;j++){
                if(board[i][j] != dest[i * N + j])    return false;
            }
        }

        return true;
    }
}

我的解法犯的关键性错误是数据结构,没有对二维数组进行处理,导致了很多本可以避免的工作。甚至连自己都不清楚为什么只花了28ms(最优解在10ms左右)

解法2(使用了高效的数据结构):

class Solution {
        public int slidingPuzzle(int[][] board) {
        Set<String> seen = new HashSet<>();
        String target = "123450";
        String s = Arrays.deepToString(board).replaceAll("\\[|\\]|,|\\s", "");
        Queue<String> q = new LinkedList<>(Arrays.asList(s));
        int ans = 0;
        int[] d = { 1, -1, 3, -3 };

        seen.add(s); 
        while (!q.isEmpty()) {
            for(int sz = q.size(); sz > 0; --sz){ 
                String str = q.poll();
                if (str.equals(target))     return ans; 
                int i = str.indexOf('0');
                for(int k = 0; k < 4; ++k){
                    int j = i + d[k];
                    if (j < 0 || j > 5 || i == 2 && j == 3 || i == 3 && j == 2)     continue;
                    char[] ch = str.toCharArray();
                    char tmp = ch[i];
                    ch[i] = ch[j];
                    ch[j] = tmp;
                    s = String.valueOf(ch);
                    if(seen.add(s))        q.offer(s);
                }
            }
            ++ans;
        }

        return -1;
    }
}

虽然还有解法比这个解法快一点,但是它应该是最简洁的解法了。关键是将二维的board转化为了字符串,因此以下步骤都很快:
1.查找0的下标。indexOf
2.放入HashSet(我的解法中自己算出的二维数组的hash。。。)
3.形成新的board
4.与目标board的对比。一个equals就解决问题了。。。

 类似资料:

相关阅读

相关文章

相关问答