773. Sliding Puzzle
Last updated
Last updated
/*
grid convert to String format:
ex:
[[1,2,3],[4,5,0]]. => 123450
[[1,2,3],[4,0,5]]. => 123405
use bfs, find least number of moves
=> change 4 direction,
[[1,2,3],
[4,0,5]]. => when 5 swap with 0 => achieve 123450
if can achieve 123450 => return steps
*/
2*3 = 6, 6! permutation of the 6 numbers,
T: O(mn + mn*(mn!)),
S:O(mn + mn!)
class Solution {
private int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int slidingPuzzle(int[][] board) {
String s = "";
for (int i = 0 ; i < board.length; i++) { // transform to String format, inorder to check result easier
for (int j = 0; j < board[0].length; j++) {
s += board[i][j];
}
}
if ("123450".equals(s)) { //find ans
return 0;
}
Set<String> visited = new HashSet<>();
Queue<String> queue = new ArrayDeque<>();
queue.offer(s);
visited.add(s);
int steps = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
String curr = queue.poll();
if ("123450".equals(curr)) { //find ans
return steps;
}
int index = curr.indexOf('0'); // find '0' index , easier!
int x = index/3; // String index to x, y index
int y = index%3;
for (int dir[] : dirs) {
int newX = x + dir[0];
int newY = y + dir[1];
if (!inArea(board, newX, newY)) {
continue;
}
int newIndex = newX*3 + newY; // new String index
String newString = swap(curr, index, newIndex); // get new String
if (visited.contains(newString)) {
continue;
}
queue.offer(newString);
visited.add(newString);
}
}
steps++;
}
return -1;
}
private boolean inArea(int[][] board, int i, int j) {
return (i >= 0 && i < board.length && j >= 0 && j < board[0].length);
}
private String swap(String s, int i, int j) {
char[] charArray = s.toCharArray();
char temp = charArray[i];
charArray[i] = charArray[j];
charArray[j] = temp;
return String.valueOf(charArray);
}
// or direct change
// private String swap(String s, int index, int newIndex) {
// char[] charArray = s.toCharArray();
// charArray[index] = charArray[newIndex];
// charArray[newIndex] = '0';
// return String.valueOf(charArray);
// }
}
// 6! permutation of the 6 numbers, 2*3 = 6
// T: O(mn + mn*(mn!)), S:O(mn + mn!)
// do dfs
// encode board to String
// 123450
// bfs from 0
// so find 0's index,
// bfs from 0 for 4 directions, visited<String> to store visited
// if (string == '123450') return steps
key:
how to define the final state? in[][] to String
how to define the move?
visited use Set<String>, for certain String pattern, we have visited...
```java
class Solution {
class Step {
String state;
int emptyIndex;
int count;
Step(String state, int emptyIndex, int count) {
this.state = state;
this.emptyIndex = emptyIndex;
this.count = count;
}
}
public int slidingPuzzle(int[][] board) {
// empty place's neightbor, we can use to swap later
int[][] swap = {{1,3},{0,4,2},{1,5},{0,4},{1,3,5},{2,4}};
StringBuilder state = new StringBuilder();
int k = 0;
int emptyIndex = -1;
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == 0) {
emptyIndex = k;
}
state.append(board[i][j]);
k++;
}
}
Set<String> visited = new HashSet<>();
Queue<Step> queue = new LinkedList<>();
queue.offer(new Step(state.toString(), emptyIndex, 0));
while (!queue.isEmpty()) {
Step cur = queue.poll();
if (visited.contains(cur.state)) {
continue;
}
if ("123450".equals(cur.state)) {
return cur.count;
}
visited.add(cur.state);
for (int position : swap[cur.emptyIndex]) {
String nextStr = swap(cur.state, position, cur.emptyIndex);
queue.offer(new Step(nextStr, position, cur.count+1));
}
}
return -1;
}
private String swap(String s, int i, int j) {
char[] c = s.toCharArray();
char temp = c[i];
c[i] = c[j];
c[j] = temp;
return String.valueOf(c);
}
}
/*
0 1 2
3 4 5 -> 0 1 2 3 4 5
{1,3}
{0,4,2}
{1,5}
{0,4}
{1,3,5}
{2,4}
*/
```