BFS
最近在为之后的暑假实习作准备,所以就开始刷算法了。接下来的都是一些刷题/学习的记录。
BFS实际上可以理解成从一个点向外部不断扩散的过程。
BFS 相对 DFS 的最主要的区别是:BFS 找到的路径一定是最短的,但代价就是空间复杂度比 DFS 大很多
不管咋说,遇到题目最简单的方式还是套框架:
// return the distance from the start to target
int BFS(Node start, Node target) {
int count = 0;
queue<Node> q;
unordered_set<Node> visited;
q.push(start);
visited.insert(start);
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
Node temp = q.front();
q.pop();
if (temp == target)
return count;
for (Node a: temp.adj()) {
if (!visited.count(a)) {
visited.insert(a);
q.push(a);
}
}
count++;
}
return -1;
}
两个例题
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int minDepth(TreeNode* root) {
if (!root)
return 0;
queue<TreeNode*> q;
q.push(root);
int level = 1;
TreeNode* ptr;
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
ptr = q.front();
if (ptr->left==nullptr&&ptr->right==nullptr) {
return level;
}
if (ptr->left)
q.push(ptr->left);
if (ptr->right)
q.push(ptr->right);
q.pop();
}
level++;
}
return level;
}
};
这题就简单套框架,几乎没有什么需要特别注意的点。
首先需要变通的地方在于,这道题有一些“危险区域”,面对这样的区域我们通过continue避开就可以了。
class Solution {
public:
string Plus(string s, int i) {
string temp = s;
if (temp[i]=='9')
temp[i] = '0';
else
temp[i] += 1;
return temp;
}
string Minus(string s, int i) {
string temp = s;
if (temp[i]=='0')
temp[i] = '9';
else
temp[i] -= 1;
return temp;
}
int openLock(vector<string>& deadends, string target) {
string start = "0000";
unordered_set<string> visited;
unordered_set<string> dead;
queue<string> q;
q.push(start);
visited.insert(start);
int count = 0;
for (string d: deadends) {
dead.insert(d);
}
while (!q.empty()) {
int size = q.size();
for (int j = 0; j < size; j++) {
string temp = q.front();
q.pop();
if (dead.count(temp))
continue;
if (temp == target)
return count;
for (int i = 0; i < 4; i++) {
string t1, t2;
t1 = Plus(temp, i);
t2 = Minus(temp, i);
if (!visited.count(t1)) {
q.push(t1);
visited.insert(t1);
}
if (!visited.count(t2)) {
q.push(t2);
visited.insert(t2);
}
}
}
count++;
}
return -1;
}
};
其实这道题还有优化的空间,我们可以通过双向BFS来进行时间复杂度的优化:
但是我们需要注意的是,双向BFS需要知道起始点和终止点。
具体代码如下:
class Solution {
public:
string Plus(string s, int i) {
string temp = s;
if (temp[i]=='9')
temp[i] = '0';
else
temp[i] += 1;
return temp;
}
string Minus(string s, int i) {
string temp = s;
if (temp[i]=='0')
temp[i] = '9';
else
temp[i] -= 1;
return temp;
}
int openLock(vector<string>& deadends, string target) {
unordered_set<string> visited;
unordered_set<string> dead;
unordered_set<string> q1, q2;
q1.insert("0000");
q2.insert(target);
int count = 0;
for (string d: deadends) {
dead.insert(d);
}
while (!q1.empty()&&!q2.empty()) {
unordered_set<string> t;
for (string c: q1) {
if (dead.count(c))
continue;
if (q2.count(c))
return count;
visited.insert(c);
for (int i = 0; i < 4; i++) {
string t1, t2;
t1 = Plus(c, i);
t2 = Minus(c, i);
if (!visited.count(t1)) {
t.insert(t1);
}
if (!visited.count(t2)) {
t.insert(t2);
}
}
}
q1 = q2;
q2 = t;
count++;
}
return -1;
}
};