一、题目
在一个 2 x 3 的板上(board)有 5块砖瓦,用数字 1~5 来表示, 以及一块空缺用 0来表示.
一次移动定义为选择 0与一个相邻的数字(上下左右)进行交换.
最终当板 board 的结果是 [[1,2,3],[4,5,0]] 谜板被解开。
给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回-1 。
点击查看原题
难度级别: 困难
二、思路
1)哈希表+BFS
思路跟752题思路大致相似。
根据当前状态,推断出接下来可能的每一步,并将访问过的状态记录下来,防止多次访问已经访问过的状态,根据状态进行BFS。
如何代表每一种状态?
在这里的思路是使用一个int型,由于是六位数,远小于int型的最大值,可以通过每一个元素占一个十进制位进行表示,确保每个状态都有一个独立的int数值表示。
如何找到下一步的状态?
此处根据表示状态的int还原位二维数组,找到零的位置后,根据零可以与相邻数字交换,从而进行记录一步交换的状态。
三、代码
1)哈希表+BFS
class Solution {public int slidingPuzzle(int[][] board) {int target = 123450;Set<Integer> visited = new HashSet();int initalLoc = getStatuInt(board);if (initalLoc == target) { // 查看起点是否目标满足要求return 0;}visited.add(initalLoc);int step = 1;Queue<Integer> q = new LinkedList();q.add(initalLoc);while (!q.isEmpty()) {int len = q.size();while (len-- > 0) { // 每次将一步的所有可能性遍历完int val = q.poll();List<Integer> nextSteps = getNextStep(val); // 获取所有下一步的可能性for (int nextStep : nextSteps) {if (visited.contains(nextStep)) { // 访问过的状态跳过continue;}if (nextStep == target) {return step;}q.add(nextStep);visited.add(nextStep);}}step++;}return -1;}private List<Integer> getNextStep(int val) {int[][] board = new int[2][3];int offset = 100000;int zeroRow = 0, zeroCol = 0;for (int i = 0; i < board.length; i++) {for (int j = 0; j < board[0].length; j++) {board[i][j] = (val/offset) % 10;offset /= 10;if (board[i][j] == 0) { // 找到0所在的位置zeroRow = i;zeroCol = j;}}}List<Integer> ans = new ArrayList();int[][] directs = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};for (int[] direct : directs) {int newVal = swapGetStatuIntAndRestore(board, zeroRow, zeroCol, zeroRow + direct[0], zeroCol + direct[1]);if (newVal != -1) {ans.add(newVal);}}return ans;}private int swapGetStatuIntAndRestore(int[][] board, int zeroRow, int zeroCol, int anthRow, int anthCol) {if (anthRow >= board.length || anthRow < 0 || anthCol >= board[0].length || anthCol < 0) {return -1;}swap(board, zeroRow, zeroCol, anthRow, anthCol);int ans = getStatuInt(board);swap(board, zeroRow, zeroCol, anthRow, anthCol);return ans;}private void swap(int[][] board, int zeroRow, int zeroCol, int anthRow, int anthCol) {int t = board[zeroRow][zeroCol];board[zeroRow][zeroCol] = board[anthRow][anthCol];board[anthRow][anthCol] = t;}private int getStatuInt(int[][] board) {int ans = 0;int offset = 100000;for (int[] row : board) {for (int i : row) {ans += offset * i;offset /= 10;}}return ans;}}
数组中元素个数为n,时间复杂度为O(n*n!),空间复杂度为O(``n*n!``)
