数字华容道——leetcode773

数字华容道——leetcode773

问题描述

在一个 2 x 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 0 来表示.

一次移动定义为选择 0 与一个相邻的数字(上下左右)进行交换.

最终当板 board 的结果是 [[1,2,3],[4,5,0]] 谜板被解开。

给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。

示例:

输入:board = [[1,2,3],[4,0,5]]
输出:1
解释:交换 0 和 5 ,1 步完成

输入:board = [[1,2,3],[5,4,0]]
输出:-1
解释:没有办法完成谜板

输入:board = [[4,1,2],[5,0,3]]
输出:5
解释:
最少完成谜板的最少移动次数是 5 ,
一种移动路径:
尚未移动: [[4,1,2],[5,0,3]]
移动 1 次: [[4,1,2],[0,5,3]]
移动 2 次: [[0,1,2],[4,5,3]]
移动 3 次: [[1,0,2],[4,5,3]]
移动 4 次: [[1,2,0],[4,5,3]]
移动 5 次: [[1,2,3],[4,5,0]]

输入:board = [[3,2,4],[1,5,0]]
输出:14

提示:
board 是一个如上所述的 2 x 3 的数组.
board[i][j] 是一个 [0, 1, 2, 3, 4, 5] 的排列.

分析

问题的本质是图的搜索,要求移动次数最少那么就是BFS搜索,例如board = [[1,2,3],[4,0,5]]把这个数组状态压缩成123405字符串,从这个字符串一步一步bfs转移成123450(0可以和2,4,5交换,可以发现和5交换一步就完成了)

代码

我在题目要求上把2和3抽取出来,再求解了最短路径

package com.lry.basic.algorithm.graph;

import java.util.*;

public class SlidingPuzzle {

    int m=3;
    int n=3;
    Map<String,String> pre = new HashMap<>();
    String end = null;
    String initState;

    public int slidingPuzzle(int[][] board) {
        Queue<String> queue = new LinkedList<>();
        //<"123540",0>value是步数
        Map<String,Integer> visited = new HashMap<>();
       
        initState = boardToStr(board);
        if(initState.equals(endStr())){
            end = initState;
            return 0;
        }
        queue.offer(initState);
        visited.put(initState,0);

        while(!queue.isEmpty()){
            String curStr = queue.poll();
            List<String> nextList = getNext(curStr);
            for(String next:nextList){
                if(!visited.containsKey(next)){
                    visited.put(next,visited.get(curStr)+1);
                    queue.offer(next);
                    //保存路径
                    pre.put(next,curStr);
                    if(next.equals(endStr())){
                        end = next;
                        return visited.get(next);
                    }
                }
            }
        }
        return -1;
    }

    private String endStr(){
        int mn = m*n;
        StringBuilder sb = new StringBuilder();
        for(int i=1;i<mn;i++){
            sb.append(i);
        }
        sb.append(0);
        return sb.toString();
    }

    private List<String> getNext(String curStr) {
        List<String> res = new ArrayList<>();
        int[][] board = strToBoard(curStr);

        int zero = 0;
        for(;zero<curStr.length();zero++){
            if(board[zero/n][zero%n]==0)break;
        }
        int zeroX = zero/n;
        int zeroY = zero%n;

        for(int i=-1;i<=1;i++){
            for(int j=-1;j<=1;j++){
                if(i==0||j==0){
                    int x = zeroX+i;
                    int y = zeroY+j;
                    if(inArea(x,y)){
                        swap(board,zeroX,zeroY,x,y);
                        res.add(boardToStr(board));
                        swap(board,zeroX,zeroY,x,y);
                    }
                }
            }
        }
        return res;
    }

    private Iterable<String> path(){
        List<String>res = new ArrayList<>();
        if(end==null){
            return res;
        }
        String cur = end;
        while(cur!=initState){
            res.add(0,cur);
            cur = pre.get(cur);
        }
        res.add(0,initState);
        return res;
    }

    private void swap(int[][] board, int zeroX, int zeroY, int x, int y) {
        int t = board[zeroX][zeroY];
        board[zeroX][zeroY] = board[x][y];
        board[x][y] = t;
    }

    private boolean inArea(int x, int y) {
        return x>=0&&x<=m-1&&y>=0&&y<=n-1;
    }

    private int[][] strToBoard(String curStr){
        int[][] board = new int[m][n];
        for(int i=0;i<curStr.length();i++){
            board[i/n][i%n] = curStr.charAt(i)-'0';
        }
        return board;
    }

    private String boardToStr(int[][] board){
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                sb.append(board[i][j]);
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        SlidingPuzzle puzzle = new SlidingPuzzle();
        System.out.println(puzzle.slidingPuzzle(new int[][]{{4,1,2},{5,0,3},{6,7,8}}));
        System.out.println(puzzle.path());
    }
}

发布了164 篇原创文章 · 获赞 81 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/LiuRenyou/article/details/103992825
今日推荐