BFS

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来进行时间复杂度的优化:

https://gblobscdn.gitbook.com/assets%2F-MOg91qJOV680ranYFeJ%2Fsync%2F946f50b8251df56bfaa1d60a133affd736e4ebb3.jpeg?alt=media

但是我们需要注意的是,双向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;
    }
};

参考

labuladong

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值