-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathSlidingPuzzle.java
More file actions
158 lines (143 loc) · 5.42 KB
/
Copy pathSlidingPuzzle.java
File metadata and controls
158 lines (143 loc) · 5.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* <p>在一个 2 x 3 的板上(<code>board</code>)有 5 块砖瓦,用数字 <code>1~5</code> 来表示, 以及一块空缺用 <code>0</code> 来表示.</p>
*
* <p>一次移动定义为选择 <code>0</code> 与一个相邻的数字(上下左右)进行交换.</p>
*
* <p>最终当板 <code>board</code> 的结果是 <code>[[1,2,3],[4,5,0]]</code> 谜板被解开。</p>
*
* <p>给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。</p>
*
* <p><strong>示例:</strong></p>
*
* <pre>
* <strong>输入:</strong>board = [[1,2,3],[4,0,5]]
* <strong>输出:</strong>1
* <strong>解释:</strong>交换 0 和 5 ,1 步完成
* </pre>
*
* <pre>
* <strong>输入:</strong>board = [[1,2,3],[5,4,0]]
* <strong>输出:</strong>-1
* <strong>解释:</strong>没有办法完成谜板
* </pre>
*
* <pre>
* <strong>输入:</strong>board = [[4,1,2],[5,0,3]]
* <strong>输出:</strong>5
* <strong>解释:</strong>
* 最少完成谜板的最少移动次数是 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]]
* </pre>
*
* <pre>
* <strong>输入:</strong>board = [[3,2,4],[1,5,0]]
* <strong>输出:</strong>14
* </pre>
*
* <p><strong>提示:</strong></p>
*
* <ul>
* <li><code>board</code> 是一个如上所述的 2 x 3 的数组.</li>
* <li><code>board[i][j]</code> 是一个 <code>[0, 1, 2, 3, 4, 5]</code> 的排列.</li>
* </ul>
* <div><div>Related Topics</div><div><li>广度优先搜索</li><li>数组</li><li>矩阵</li></div></div><br><div><li>👍 242</li><li>👎 0</li></div>
*/
package leetcode7;
import java.util.HashSet;
import java.util.Set;
public class SlidingPuzzle {
public static void main(String[] args) {
Solution solution = new SlidingPuzzle().new Solution();
}
//leetcode submit region begin(Prohibit modification and deletion)
/**
* BFS常规解法,题目很简单,注:
* 1. 只需要使 board 数组可哈希,转为字符串即可
* 2. 记录每一次的中间结果,避免重复计算。不必记录中间结果的次数,记录的中间结果均为最小次数。
*/
class Solution {
private int[][] pointList = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0},};
private String endStr = "123450";
public int slidingPuzzle(int[][] board) {
Set<String> memo = new HashSet<>();
Set<String> startSet = new HashSet<>();
startSet.add(convert(board));
int res = 0;
while (!startSet.isEmpty()) {
if (startSet.contains(endStr)) {
return res;
}
startSet = solve(startSet, memo);
res++;
}
return -1;
}
private Set<String> solve(Set<String> startSet, Set<String> memo) {
Set<String> newStartSet = new HashSet<>();
for (String startStr : startSet) {
int[][] startBoard = convert(startStr);
int[] zero = findZero(startBoard);
for (int[] point : pointList) {
if (swap(startBoard, zero[0], zero[1], zero[0] + point[0], zero[1] + point[1])) {
calc(startBoard, newStartSet, memo);
swap(startBoard, zero[0], zero[1], zero[0] + point[0], zero[1] + point[1]);
}
}
}
return newStartSet;
}
private int[] findZero(int[][] board) {
for (int x = 0; x < board.length; x++) {
for (int y = 0; y < board[0].length; y++) {
if (board[x][y] == 0) {
return new int[]{x, y};
}
}
}
return null;
}
private boolean swap(int[][] startBoard, int x1, int y1, int x2, int y2) {
if (x2 < 0 || y2 < 0 || x2 >= 2 || y2 >= 3) {
return false;
}
int temp = startBoard[x1][y1];
startBoard[x1][y1] = startBoard[x2][y2];
startBoard[x2][y2] = temp;
return true;
}
private void calc(int[][] startBoard, Set<String> newStartSet, Set<String> memo) {
String startStr = convert(startBoard);
if (memo.contains(startStr)) {
return;
}
newStartSet.add(startStr);
memo.add(startStr);
}
private String convert(int[][] board) {
StringBuilder builder = new StringBuilder();
for (int x = 0; x < board.length; x++) {
for (int y = 0; y < board[0].length; y++) {
builder.append(board[x][y]);
}
}
return builder.toString();
}
private int[][] convert(String boardStr) {
int[][] board = new int[2][3];
int i = 0;
for (int x = 0; x < board.length; x++) {
for (int y = 0; y < board[0].length; y++) {
board[x][y] = boardStr.charAt(i++) - 0x30;
}
}
return board;
}
}
//leetcode submit region end(Prohibit modification and deletion)
}