【五月集训5.17】———广搜

请添加图片描述

☘前言☘

开更五月集训专题,由浅入深,深入浅出,飞向大厂!

🧑🏻作者简介:一个从工业设计改行学嵌入式的年轻人
✨联系方式:2201891280(QQ)
全文大约阅读时间: 20min



LCP 44. 开幕式焰火

LCP 44. 开幕式焰火

解题思路

利用hash表记录然后广搜就完事了。

代码

class Solution {
    
public:
    int numColor(TreeNode* root) {
        bool hash[1001] = {0};
        int ans = 0;
        queue<TreeNode*>   dui;
        dui.push(root);
        while(!dui.empty()){
            root = dui.front();
            dui.pop();
            if(root->left)  dui.push(root->left);
            if(root->right) dui.push(root->right);
            if(!hash[root->val]) hash[root->val] = true,++ans;
        }
        return ans;
    }
};

注意的点

这就是个广搜模板,务必熟稔于心。


102. 二叉树的层序遍历

102. 二叉树的层序遍历

解题思路

和上一题其实思路是一样的,只不过需要找下一层的起点,我这里的思路有一个标志位,如果到新的以为就开始寻找下一层的起点位置,如果能找到一个孩子节点就是下一层的起始位置。

代码

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        queue<TreeNode *> dui;

        if(!root)   return ans;
        TreeNode * nextchild = root;
        bool flag = false;  //记录标志位
        dui.push(root);
        while(!dui.empty()){
            root = dui.front();dui.pop();   //出队并记录第一个元素
            if(root == nextchild)   flag = true,ans.push_back({root->val});       //开始新的一层
            else    ans.back().push_back(root->val);
            if(root->left){
                dui.push(root->left);
                if(flag)    flag = false,nextchild = root->left;
            }
            if(root->right){
                dui.push(root->right);
                if(flag)    flag = false,nextchild = root->right;
            }
        }
        return ans;
    }
};

注意的点

  1. 空需要特判,不特判过不去。
  2. 查找下一层一定要先左后右。毕竟是每一层的起点。

1609. 奇偶树

1609. 奇偶树

解题思路

利用一下上一题的代码,当换层的时候进行odd的反转。

代码

class Solution {
public:
    bool isEvenOddTree(TreeNode* root) {
        queue<TreeNode *> dui;

        TreeNode * nextchild = root;
        bool flag = false;  //记录标志位
        dui.push(root);
        bool odd = false;    //-1行是偶数
        int pre = 0;
        while(!dui.empty()){
            root = dui.front();dui.pop();   //出队并记录第一个元素
            if(root == nextchild)   flag = true,odd = !odd;      //开始新的一层反奇偶性
            else if(odd && root->val <= pre) return false;   //奇数层但是减少
            else if(!odd && root->val >= pre)   return false;   //偶数层但是增加
            pre = root->val;
            if(odd ^ (root->val % 2))   return false;   //需要是偶数 但是结果是奇数 或者相反都是错的
            if(root->left){
                dui.push(root->left);
                if(flag)    flag = false,nextchild = root->left;
            }
            if(root->right){
                dui.push(root->right);
                if(flag)    flag = false,nextchild = root->right;
            }
        }
        return true;
    }
};

注意的点

  1. odd进行反转 第一次是-1行的奇偶行
  2. 判断奇偶性是否满足可以用位运算进行优化

1263. 推箱子

1263. 推箱子

解题思路

使用状态压缩,然后进行遍历,记录每个状态的结果。

代码

class Solution {
    int ans[1<<20]; //每个状态的结果
    int sx, sy, bx, by; //四个坐标
    int csize, rsize;   //列数和行数
    int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};//四个方向
    int pack(){
        return sx << 15 | sy << 10 | bx << 5 | by;
        } //状态压缩 优先级<< 大于|
    void unpack(int now){
        sx = now >> 15;sy = now >> 10 & 31;bx = now >> 5 & 31;by = now &31;
    } //状态压缩 优先级<< 大于|
    bool isRun(vector<vector<char>>& grid,int x ,int y){    //判断是否合法
        if(x < 0|| x >= csize || y < 0|| y >= rsize || grid[y][x] == '#')
            return false;//出界或者是墙
        return true;
    }

public:
    int minPushBox(vector<vector<char>>& grid) {
        queue<int> dui;
        rsize = grid.size(),csize = grid[0].size();
        memset(ans,-1,sizeof(ans)); //初始化
        //处理箱子和人的位置
        for(int i = 0;i < rsize;++i)
            for(int j = 0;j < csize;++j)
                if(grid[i][j] == 'S')   
                    sx = j,sy = i,grid[i][j] = '.';
                else if(grid[i][j] == 'B')
                    bx = j,by = i,grid[i][j] = '.';
        int tmp = pack();
        ans[tmp] = 0;
        dui.push(tmp);  //根节点
        int ret = -1;
        //层序遍历
        while(!dui.empty()){
            tmp = dui.front();dui.pop();//拿到队头元素并出队
            unpack(tmp);//写入全局变量
            if(grid[by][bx] == 'T' && (ret == -1 || ans[tmp] < ret))
                ret = ans[tmp];
            for(int i = 0;i < 4;++i){
                sx += dir[i][0];
                sy += dir[i][1];
                if(isRun(grid,sx,sy)){
                    if(sx == bx && sy == by){ //是个箱子
                        bx += dir[i][0];
                        by += dir[i][1];
                        if(isRun(grid,bx,by)){//箱子能推
                            int tmpi = pack();
                            if(ans[tmp] + 1 < ans[tmpi]|| ans[tmpi] == -1){	//推一下哈
                                ans[tmpi] = ans[tmp] + 1;
                                dui.push(tmpi);
                            }
                        }

                        bx -= dir[i][0];
                        by -= dir[i][1];
                    }else{
                        int tmpi = pack();
                        if(ans[tmp] < ans[tmpi] || ans[tmpi] == -1){
                            ans[tmpi] = ans[tmp];
                            dui.push(tmpi);
                        }
                    }
                }
                sx -= dir[i][0];
                sy -= dir[i][1];
            }
        }
        return ret;
    }
};

注意的点

看的脑子疼。

写在最后

广搜一直是我的弱项。最后一题要了命了0.0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XingleiGao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值