题意
给定一个2*3的矩阵,元素是0-5,移动元素0和他周围的格子交换,需要得到[1,2,3], [4,5,0],求最少的交换次数,如果无法得到答案则返回-1
链接
https://leetcode.com/problems/sliding-puzzle/
思考
含有"最少"字样,会想到bfs,对于这道题,最少的交换次数就是bfs的层数
思路
直接比较二维矩阵比较慢,可以转化成字符串比较。把格子的初始化成一个字符串,该终止状态是"123450"。bfs搜索每一次交换空白格子之后的状态
模版
对于
(
m
∗
n
)
(m * n)
(m∗n)二维矩阵转一维,
对于第i行第j列元素
(
i
,
j
)
(i, j)
(i,j),转化成一维的下标是
i
∗
m
+
j
i*m+j
i∗m+j
一维下标(t)转化成二维,
x
=
t
/
m
x = t/m
x=t/m, y = t mod m
注意点
- queue在c++中是q.front(), q.pop()
- 对于c++的循环而言,每一次迭代都会重新计算循环体中的变量,如果循环结构写成
for(int i = 0; i < q.size(); i++)
结果是会出错的
int qSize = q.size();
for (int i = 0; i < qSize; i++) {
}
题解
class Solution {
public:
int slidingPuzzle(vector<vector<int>>& a) {
int m = a.size();
int n = a[0].size();
string input = "";
int res = 0;
set<string> vis;
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
input += '0' + a[i][j];
}
}
queue<string> q;
q.push(input);
vis.insert(input);
while(q.size()) {
int qlen = q.size();
for(int i = 0; i < qlen; i++) {
string node = q.front();
q.pop();
if(node == "123450") return res;
int id = node.find('0');
int x = id/3;
int y = id%3;
int dk[] = {-1, 0, 1, 0, -1};
for(int j = 0; j < 4; j++) {
int nx = x + dk[j];
int ny = y + dk[j+1];
if(nx >= 0 && nx < m && ny >= 0 && ny < n) {
string temp = node;
swap(temp[id], temp[nx*3+ny]);
if(!vis.count(temp)) {
q.push(temp);
vis.insert(temp);
}
}
}
}
res += 1;
}
return -1;
}
};
时间复杂度:
O
(
V
!
)
O(V!)
O(V!) V是状态的数量
空间复杂度:
O
(
V
!
)
O(V!)
O(V!) V是状态的数量