LeetCode随笔之BFS广度优先搜索

  1. (迷宫初级版)
  2. (迷宫进阶版)假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
//这题就是普通的bfs多了‘钥匙’这个状态
//所以book[x][y][key]的意义就是 横坐标为x,纵坐标为y,钥匙状态为key的点是否访问过
//钥匙的状态 就用二进制数表示 最多10 把钥匙 那就是1024
//比如我现在有第二把钥匙和第四把钥匙  那么我的钥匙状态就是 0101000000 也就是 320
#include <iostream>
#include <sstream>
#include <string>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <bitset>

using namespace std;
bool book[105][105][1200];
int NEXT[4][2]={0,1,0,-1,1,0,-1,0};

struct node
{
    int x,y,key,step;
    node(int x,int y, int key,int step):x(x),y(y),key(key),step(step){}
};
int bfs(int x1,int y1,vector<vector<char>> &G,int &m, int &n);
int main(){
    int n,m;
    int x1,y1;
    cin>>m>>n;
        vector<vector<char>> G(m,vector<char> (n));
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                cin>>G[i][j];
                if(G[i][j]=='2'){
                    x1=i;y1=j;
                }
            }
        }

        int out=bfs(x1,y1,G,m,n);
        cout<<out;

    system("pause");
    return 0;
}
int bfs(int x1,int y1,vector<vector<char>> &G,int &m, int &n){

    book[x1][y1][0]=1;//表示是否走过

    queue<node> Q;
    Q.push(node(x1,y1,0,0));
    while(!Q.empty()){
        node head=Q.front();Q.pop();
        if(G[head.x][head.y]=='3') return head.step;
        for(int i=0;i<4;i++){
            int nx=head.x+NEXT[i][0],ny=head.y+NEXT[i][1];
            if(nx>=m||nx<0||ny>=n||ny<0||G[nx][ny]=='0') continue;
            int key=head.key;
            if('a'<=G[nx][ny]&&G[nx][ny]<='z') key=key|(1<<(G[nx][ny]-'a'));
            if('A'<=G[nx][ny]&&G[nx][ny]<='Z'&&(key&(1<<(G[nx][ny]-'A')))==0) continue;
            if(!book[nx][ny][key]){
                book[nx][ny][key]=1;
                Q.push(node(nx,ny,key,head.step+1));
            }
        }
    }
    return 0;
}

3. 找到树每层最大值

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        if(root==NULL) return vector<int>(0);
        queue<TreeNode*> q;
        q.push(root);
        int i=0;
        vector<int> maxValue;
        while(!q.empty())
        {
            i++;
            int k=q.size();
            maxValue.push_back(findmax(q));

            for(int j=0;j<k;j++)
            {
                TreeNode* f=q.front();
                if(f->left) q.push(f->left);
                if(f->right) q.push(f->right);
                q.pop();
            }

        }
        return maxValue;
    }
    int findmax(queue<TreeNode*> q)
    {
        queue<TreeNode*> q2=q;
        int max=-2147483648;
        while(!q2.empty())
        {
            TreeNode* tmp=q2.front();
            q2.pop();
            int tmpvalue=tmp->val;
            max=tmpvalue>=max? tmpvalue:max;
        }
        return max;
    }
};

4. 求树的最小深度。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
/*
DFS版本
int minDepth(TreeNode* root) {
    if (!root) return 0;
    int L = minDepth(root->left), R = minDepth(root->right);
    return 1 + (L && R ? min(L, R) : max(L, R)); 
}
*/
class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        queue<TreeNode*> Q;
        Q.push(root);
        int i=0;
        while(!Q.empty())
        {
            i++;
            int k=Q.size();
            for(int j=0;j<k;j++)
            {
                TreeNode* rt=Q.front();
                if(rt->left) Q.push(rt->left);
                if(rt->right) Q.push(rt->right);
                Q.pop();
                if(rt->left==NULL && rt->right==NULL) return i;
            }
        }
        return -1;
    }
};
  1. Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, …) which sum to n.

For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.

//最复杂的思路,但是却通用。
//也就是说,如果要求满足和为sum条件的有多少个,但是这种情况下4+9和9+4算做一种!!!注意!采用:
for(int i=0;i<n;i++){
    for(int j=sum;j>=A[i];j--){//倒叙为数不可重复使用,正序为可重复
        dp[j]+=dp[j-A[i]];
    }
}
//如果要求满足和为sum条件的,最少有几个数相加,则采用
for(int i=0;i<n;i++){//同理正序可重复,倒叙不可重复!其实就是和从dp[sum]开始算起还是从dp[0]算起的区别。
    for(int j=sum;j>=A[i];j--){
        dp[j]=dp[j-A[i]]+1;
    }
}
class Solution {
public:
    int numSquares(int m) {
        int n=(int)sqrt((float)m);
        vector<vector<int>> dp(m+1,vector<int> (m+1,0));
        dp[0][0]=1;
        vector<int> res;
        for(int i=n;i>0;i--){
            for(int k=1;k<=m;k++){
                for(int j=i*i;j<=m;j++){
                    dp[k][j]+=dp[k-1][j-i*i];//代表k个数相加且和为j的情况总共有多少种了。
                }
                if(dp[k][m]!=0) res.push_back(k);
            }
        }
        int out=INT_MAX;
        for(int i=0;i<res.size();i++)
        {
            out=min(res[i],out);
        }
        return out;
    }
};
//简单点的思路:
class Solution {
public:
    int numSquares(int m) {
        int n=(int)sqrt((float)m);
        //vector<vector<int>> dp(m+1,vector<int> (m+1,0));
        vector<int> dp(m+1,0);
        dp[0]=0;

        vector<int> res;
        for(int j=1;j<=m;j++){//分别就和为1...m,计算dp[j]在所有待选择数据中选择数据的个数
            int minV=INT_MAX;
            for(int i=1;i*i<=j;i++ ){
                minV=min(minV,dp[j-i*i]+1);//dp[j]代表和为j,现在有几个数相加。
                dp[j]=minV;
            }
        }
        return dp[m];
    }
};
  1. Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.
Example 1:
Input:
0 0 0
0 1 0
1 1 1
Output:
0 0 0
0 1 0
1 2 1

//这种方法超时了...但是结果是对的。
struct node{
    int x,y;
    int step;
    node(int x,int y,int step):x(x),y(y),step(step) {}
};
class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        int m=matrix.size();int n=matrix[0].size();

        int dir[4][2]={0,1,0,-1,1,0,-1,0};
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(matrix[i][j]!=0){
                    vector<vector<int>> book(m,vector<int> (n,0));
                    queue<node> Q;
                    Q.push(node(i,j,0));
                    while(!Q.empty()){
                        node head=Q.front();Q.pop();
                        if (matrix[head.x][head.y]==0) 
                            {matrix[i][j]=head.step;break;}
                        for(int k=0;k<4;k++){
                            int nx=head.x+dir[k][0];int ny=head.y+dir[k][1];
                            if(nx<0||nx>=m||ny<0||ny>=n)continue;
                            if(book[nx][ny]==0){
                                book[nx][ny]=1;
                                Q.push(node(nx,ny,head.step+1));
                            }
                        }   
                    }

                }
            }
        }
        return matrix;
    }
};
//可以用动态规划来做,省心省力。
class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        int h=matrix.size(), w=matrix[0].size();
        vector<vector<int>> dp(h,vector<int>(w,INT_MAX));
        for(int times=0;times<=1;times++) // two passes, first forward then backward
            for(int i=times?h-1:0;times?i>=0:i<h;times?i--:i++) 
                for(int j=times?w-1:0;times?j>=0:j<w;times?j--:j++)
                        if(matrix[i][j]==0)
                            dp[i][j]=0;
                        else {
                            if(i&&dp[i-1][j]!=INT_MAX&&dp[i][j]>dp[i-1][j]+1) // look up
                                dp[i][j]=dp[i-1][j]+1;
                            if(j&&dp[i][j-1]!=INT_MAX&&dp[i][j]>dp[i][j-1]+1) // look left
                                dp[i][j]=dp[i][j-1]+1;
                            if(i<h-1&&dp[i+1][j]!=INT_MAX&&dp[i][j]>dp[i+1][j]+1) // look down
                                dp[i][j]=dp[i+1][j]+1;
                            if(j<w-1&&dp[i][j+1]!=INT_MAX&&dp[i][j]>dp[i][j+1]+1) // look right
                                dp[i][j]=dp[i][j+1]+1;
                        }
        return dp;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值