☘前言☘
开更五月集训专题,由浅入深,深入浅出,飞向大厂!
🧑🏻作者简介:一个从工业设计改行学嵌入式的年轻人
✨联系方式:2201891280(QQ)
⏳全文大约阅读时间: 20min
全文目录
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. 二叉树的层序遍历
解题思路
和上一题其实思路是一样的,只不过需要找下一层的起点,我这里的思路有一个标志位,如果到新的以为就开始寻找下一层的起点位置,如果能找到一个孩子节点就是下一层的起始位置。
代码
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;
}
};
注意的点
- 空需要特判,不特判过不去。
- 查找下一层一定要先左后右。毕竟是每一层的起点。
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;
}
};
注意的点
- odd进行反转 第一次是-1行的奇偶行
- 判断奇偶性是否满足可以用位运算进行优化
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